adonisjs-server-stats 1.11.6 → 1.12.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 (82) hide show
  1. package/README.md +13 -0
  2. package/dist/core/explain-utils.d.ts +77 -0
  3. package/dist/core/index.d.ts +8 -2
  4. package/dist/core/index.js +1089 -877
  5. package/dist/core/queries-columns.d.ts +42 -0
  6. package/dist/core/queries-controller.d.ts +94 -0
  7. package/dist/core/query-utils.d.ts +49 -0
  8. package/dist/core/types-diagnostics.d.ts +2 -0
  9. package/dist/react/{CacheSection-BYN53kYO.js → CacheSection-DZFOiOYH.js} +1 -1
  10. package/dist/react/{CacheTab-DOhuK05d.js → CacheTab-D8js5o69.js} +1 -1
  11. package/dist/react/{ConfigSection-B9EHh4Rp.js → ConfigSection-DoJmvNkF.js} +1 -1
  12. package/dist/react/{ConfigTab-C8kriE2b.js → ConfigTab-CDvljuBF.js} +1 -1
  13. package/dist/react/{CustomPaneTab-CvzQS_Wh.js → CustomPaneTab-Db9eIQ-9.js} +1 -1
  14. package/dist/react/{EmailsSection-BJyFJf7A.js → EmailsSection-D7oxvAjA.js} +1 -1
  15. package/dist/react/{EmailsTab-Ch8jp10B.js → EmailsTab-BITuGTQm.js} +1 -1
  16. package/dist/react/{EventsSection-DJPwHeT8.js → EventsSection-7mDZv70I.js} +1 -1
  17. package/dist/react/{EventsTab-B-FoehXC.js → EventsTab-DF13BChE.js} +1 -1
  18. package/dist/react/InternalsContent-BNOnSoi9.js +393 -0
  19. package/dist/react/{InternalsSection-B6VlVx5f.js → InternalsSection-BwrTfpjA.js} +1 -1
  20. package/dist/react/{InternalsTab-CkEKpRMU.js → InternalsTab--RD-L1dX.js} +1 -1
  21. package/dist/react/{JobsSection-DWF4i1t_.js → JobsSection-B_VJFWy6.js} +1 -1
  22. package/dist/react/{JobsTab-DqnifQXV.js → JobsTab-DK8Fl9nz.js} +1 -1
  23. package/dist/react/{LogEntryRow-CMMkqA9M.js → LogEntryRow-Bdie9SFe.js} +1 -1
  24. package/dist/react/{LogsSection-C1xC5aP4.js → LogsSection-CrWqxWRr.js} +2 -2
  25. package/dist/react/{LogsTab-CS4sLfLw.js → LogsTab-DYSpL637.js} +2 -2
  26. package/dist/react/{OverviewSection-CxvfOR0v.js → OverviewSection-CuaccMZt.js} +1 -1
  27. package/dist/react/QueriesContent-BDIx8zFn.js +288 -0
  28. package/dist/react/QueriesSection-CvGGh5Ij.js +117 -0
  29. package/dist/react/QueriesTab-C7CCwhVc.js +87 -0
  30. package/dist/react/{RequestsSection-DETN9oZb.js → RequestsSection-mENyeNsk.js} +2 -2
  31. package/dist/react/{RoutesSection-CmorkJeC.js → RoutesSection-DjovlaNS.js} +1 -1
  32. package/dist/react/{RoutesTab-CbzBOzpc.js → RoutesTab-CbQECiUc.js} +1 -1
  33. package/dist/react/{SplitPaneWrapper-BiIgT4ND.js → SplitPaneWrapper-DyRyH5Re.js} +1 -1
  34. package/dist/react/{TimelineTab-Ue9tUD_n.js → TimelineTab-BKTFbsPe.js} +2 -2
  35. package/dist/react/components/Dashboard/shared/DataTable.d.ts +1 -1
  36. package/dist/react/components/shared/QueriesContent.d.ts +33 -0
  37. package/dist/react/{index-DwDK-4oX.js → index-CAUHa8QX.js} +2 -2
  38. package/dist/react/index.js +1 -1
  39. package/dist/react/style.css +1 -1
  40. package/dist/src/collectors/db_pool_collector.js +17 -23
  41. package/dist/src/dashboard/query_explain_handler.d.ts +11 -0
  42. package/dist/src/dashboard/query_explain_handler.js +64 -11
  43. package/dist/src/debug/query_collector.d.ts +1 -0
  44. package/dist/src/debug/query_collector.js +3 -0
  45. package/dist/src/edge/client/dashboard.js +2 -2
  46. package/dist/src/edge/client/debug-panel-deferred.js +1 -1
  47. package/dist/src/edge/client-vue/dashboard.js +4 -4
  48. package/dist/src/edge/client-vue/debug-panel-deferred.js +2 -2
  49. package/dist/src/provider/diagnostics.d.ts +3 -0
  50. package/dist/src/provider/diagnostics.js +1 -0
  51. package/dist/src/provider/server_stats_provider.d.ts +7 -0
  52. package/dist/src/provider/server_stats_provider.js +38 -0
  53. package/dist/src/routes/debug_routes.d.ts +4 -0
  54. package/dist/src/routes/debug_routes.js +45 -0
  55. package/dist/src/routes/register_routes.d.ts +4 -0
  56. package/dist/src/routes/register_routes.js +2 -0
  57. package/dist/src/styles/components.css +254 -0
  58. package/dist/src/styles/dashboard.css +26 -185
  59. package/dist/src/styles/debug-panel.css +2 -24
  60. package/dist/vue/{CacheSection-DT2Mwf_s.js → CacheSection-Bx41lpfK.js} +1 -1
  61. package/dist/vue/{ConfigSection-BwKwS9lh.js → ConfigSection-fkfUdCmx.js} +1 -1
  62. package/dist/vue/{EmailsSection-B65g0FVS.js → EmailsSection-CbcDKF9Q.js} +1 -1
  63. package/dist/vue/{EventsSection-CxqtVF-o.js → EventsSection-CWbTYOBi.js} +1 -1
  64. package/dist/vue/{InternalsSection-BJUXE-5F.js → InternalsSection-jhTCuK3j.js} +149 -130
  65. package/dist/vue/{InternalsTab-DEMjqtlw.js → InternalsTab-521fxYYj.js} +152 -133
  66. package/dist/vue/{JobsSection-rMIyMb-g.js → JobsSection-CGGO6rtS.js} +1 -1
  67. package/dist/vue/{LogsSection-DmmZVJ7D.js → LogsSection-BPB-C-XA.js} +1 -1
  68. package/dist/vue/{OverviewSection-BMabyqw-.js → OverviewSection-BTcnPeoM.js} +1 -1
  69. package/dist/vue/QueriesSection-2SE3igQJ.js +411 -0
  70. package/dist/vue/QueriesTab-DO5XwJ--.js +112 -0
  71. package/dist/vue/{RequestsSection-CTu4jPZ_.js → RequestsSection-DXcG5Zok.js} +1 -1
  72. package/dist/vue/{RoutesSection-zQZDedL7.js → RoutesSection-BkNGWdoP.js} +1 -1
  73. package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts +1 -41
  74. package/dist/vue/{index-CM3yNVUR.js → index-CptF6Qbp.js} +2 -2
  75. package/dist/vue/index.js +1 -1
  76. package/dist/vue/style.css +1 -1
  77. package/package.json +1 -1
  78. package/dist/react/InternalsContent-O8ino9oM.js +0 -370
  79. package/dist/react/QueriesSection-CrMdU5Ax.js +0 -458
  80. package/dist/react/QueriesTab-x85PjkyS.js +0 -88
  81. package/dist/vue/QueriesSection-BfDFwGqH.js +0 -428
  82. package/dist/vue/QueriesTab-DuTG7cpC.js +0 -106
@@ -0,0 +1,288 @@
1
+ import { jsxs as l, jsx as e, Fragment as x } from "react/jsx-runtime";
2
+ import { useMemo as E } from "react";
3
+ import { buildSqlCounts as R, getDashboardGroupedColumns as z, getDashboardListColumns as K, durationClassName as S, resolveSqlMethod as F, resolveTimestamp as H, resolveNormalizedSql as L, hasNestedPlan as U, getExplainColumns as V, formatCellValue as X, flattenPlanTree as B } from "adonisjs-server-stats/core";
4
+ import { F as A } from "./FilterBar-CQ7bD669.js";
5
+ import { T as J } from "./TimeAgoCell-o3KigGfM.js";
6
+ import { D as I } from "./DataTable-YyShr5B-.js";
7
+ import { P as W } from "./Pagination-BkmzUDY8.js";
8
+ function Y({ node: s, depth: d = 0 }) {
9
+ if (!s) return null;
10
+ const i = E(() => B(s, d), [s, d]);
11
+ return /* @__PURE__ */ e(x, { children: i.map((r, o) => /* @__PURE__ */ l("div", { className: "ss-dash-explain-node", style: { marginLeft: `${r.depth * 20}px` }, children: [
12
+ /* @__PURE__ */ l("div", { className: "ss-dash-explain-node-header", children: [
13
+ /* @__PURE__ */ e("span", { className: "ss-dash-explain-node-type", children: r.nodeType }),
14
+ r.relationName && /* @__PURE__ */ l(x, { children: [
15
+ " on ",
16
+ /* @__PURE__ */ e("strong", { children: r.relationName })
17
+ ] }),
18
+ r.alias && ` (${r.alias})`,
19
+ r.indexName && /* @__PURE__ */ l(x, { children: [
20
+ " using ",
21
+ /* @__PURE__ */ e("em", { children: r.indexName })
22
+ ] })
23
+ ] }),
24
+ r.metrics.length > 0 && /* @__PURE__ */ e("div", { className: "ss-dash-explain-metrics", children: r.metrics.join(" · ") })
25
+ ] }, o)) });
26
+ }
27
+ function Z({ plan: s }) {
28
+ if (!s || !Array.isArray(s) || s.length === 0)
29
+ return /* @__PURE__ */ e("div", { className: "ss-dash-explain-result", children: "No plan data returned" });
30
+ const d = s[0];
31
+ if (U(d))
32
+ return /* @__PURE__ */ e("div", { className: "ss-dash-explain-result", children: /* @__PURE__ */ e(Y, { node: d.Plan, depth: 0 }) });
33
+ if (typeof d == "object" && d !== null) {
34
+ const i = V(s);
35
+ return /* @__PURE__ */ e("div", { className: "ss-dash-explain-result", children: /* @__PURE__ */ l("table", { children: [
36
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ e("tr", { children: i.map((r) => /* @__PURE__ */ e("th", { children: r }, r)) }) }),
37
+ /* @__PURE__ */ e("tbody", { children: s.map((r, o) => {
38
+ const c = r;
39
+ return /* @__PURE__ */ e("tr", { children: i.map((n) => /* @__PURE__ */ e("td", { children: X(c[n]) }, n)) }, o);
40
+ }) })
41
+ ] }) });
42
+ }
43
+ return /* @__PURE__ */ e("div", { className: "ss-dash-explain-result", children: "No plan data returned" });
44
+ }
45
+ const $ = /* @__PURE__ */ l("span", { className: "ss-empty-hint", children: [
46
+ "Queries require ",
47
+ /* @__PURE__ */ e("code", { children: "debug: true" }),
48
+ " on your Lucid connections in",
49
+ " ",
50
+ /* @__PURE__ */ e("code", { children: "config/database.ts" })
51
+ ] });
52
+ function de({
53
+ mode: s,
54
+ controllerState: d,
55
+ queries: i,
56
+ meta: r,
57
+ isLoading: o,
58
+ onSearchChange: c,
59
+ onSort: n,
60
+ onToggleExpand: a,
61
+ onViewModeChange: t,
62
+ onPageChange: p,
63
+ onExplain: u,
64
+ onCloseExplain: h,
65
+ summary: y,
66
+ filterBarChildren: b
67
+ }) {
68
+ const { viewMode: g, sort: N, expandedIds: C, explainData: D, search: P } = d, q = !!u, T = s === "dashboard" && !!r, j = s === "dashboard" && !!t, M = E(() => R(i), [i]);
69
+ if (j && g === "grouped")
70
+ return G();
71
+ return _();
72
+ function G() {
73
+ const k = z().map(
74
+ (w) => ee(w, C, a)
75
+ );
76
+ return /* @__PURE__ */ l("div", { children: [
77
+ /* @__PURE__ */ e(A, { search: P, onSearchChange: c, placeholder: "Filter queries...", summary: y, children: b }),
78
+ o && i.length === 0 ? /* @__PURE__ */ e("div", { className: "ss-dash-empty", children: "Loading queries..." }) : /* @__PURE__ */ e("div", { className: "ss-dash-table-wrap", children: /* @__PURE__ */ e(
79
+ I,
80
+ {
81
+ columns: k,
82
+ data: i,
83
+ keyField: "sqlNormalized",
84
+ sort: N.key,
85
+ sortDir: N.dir,
86
+ onSort: n,
87
+ emptyMessage: /* @__PURE__ */ l(x, { children: [
88
+ "No queries recorded",
89
+ $
90
+ ] })
91
+ }
92
+ ) })
93
+ ] });
94
+ }
95
+ function _() {
96
+ const v = K({ showExplain: q }), k = v.map(
97
+ (f) => se(f, C, M, D, a, u)
98
+ ), w = v.length, O = q ? (f) => {
99
+ const Q = f.id, m = D.get(Q);
100
+ return !m || m.loading ? null : /* @__PURE__ */ e("tr", { className: "ss-dash-explain-row", children: /* @__PURE__ */ e("td", { colSpan: w, className: "ss-dash-explain", children: /* @__PURE__ */ l("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "start" }, children: [
101
+ /* @__PURE__ */ e("div", { style: { flex: 1 }, children: m.error ? /* @__PURE__ */ l("div", { className: "ss-dash-explain-result ss-dash-explain-error", children: [
102
+ /* @__PURE__ */ e("strong", { children: "Error:" }),
103
+ " ",
104
+ m.error,
105
+ m.result?.message && /* @__PURE__ */ l(x, { children: [
106
+ /* @__PURE__ */ e("br", {}),
107
+ m.result.message
108
+ ] })
109
+ ] }) : m.result ? /* @__PURE__ */ e(Z, { plan: m.result.plan || m.result.rows || [] }) : null }),
110
+ /* @__PURE__ */ e(
111
+ "button",
112
+ {
113
+ type: "button",
114
+ className: "ss-dash-explain-btn",
115
+ onClick: () => h?.(),
116
+ style: { marginLeft: "8px", flexShrink: 0 },
117
+ children: "Close"
118
+ }
119
+ )
120
+ ] }) }) });
121
+ } : void 0;
122
+ return /* @__PURE__ */ l("div", { children: [
123
+ /* @__PURE__ */ e(A, { search: P, onSearchChange: c, placeholder: "Filter queries...", summary: y, children: b }),
124
+ o && i.length === 0 ? /* @__PURE__ */ e("div", { className: "ss-dash-empty", children: "Loading queries..." }) : /* @__PURE__ */ l(x, { children: [
125
+ /* @__PURE__ */ e("div", { className: "ss-dash-table-wrap", children: /* @__PURE__ */ e(
126
+ I,
127
+ {
128
+ columns: k,
129
+ data: i,
130
+ sort: N.key,
131
+ sortDir: N.dir,
132
+ onSort: n,
133
+ emptyMessage: /* @__PURE__ */ l(x, { children: [
134
+ "No queries captured",
135
+ $
136
+ ] }),
137
+ renderAfterRow: O
138
+ }
139
+ ) }),
140
+ T && r && /* @__PURE__ */ e(
141
+ W,
142
+ {
143
+ page: r.page,
144
+ lastPage: r.lastPage,
145
+ total: r.total,
146
+ onPageChange: p
147
+ }
148
+ )
149
+ ] })
150
+ ] });
151
+ }
152
+ }
153
+ function ee(s, d, i) {
154
+ const r = {
155
+ key: s.key,
156
+ label: s.label,
157
+ width: s.width,
158
+ sortable: s.sortable
159
+ };
160
+ switch (s.type) {
161
+ case "sql":
162
+ r.render = (o, c) => {
163
+ const n = o || "", a = (c.count || 0) >= 3;
164
+ return /* @__PURE__ */ l(x, { children: [
165
+ /* @__PURE__ */ e(
166
+ "span",
167
+ {
168
+ className: `ss-dash-sql ${d.has(n) ? "ss-dash-expanded" : ""}`,
169
+ title: "Click to expand",
170
+ onClick: (t) => {
171
+ t.stopPropagation(), i(n);
172
+ },
173
+ role: "button",
174
+ tabIndex: 0,
175
+ onKeyDown: (t) => t.key === "Enter" && i(n),
176
+ children: n
177
+ }
178
+ ),
179
+ a && /* @__PURE__ */ l(x, { children: [
180
+ " ",
181
+ /* @__PURE__ */ e("span", { className: "ss-dash-dup", children: "DUP" })
182
+ ] })
183
+ ] });
184
+ };
185
+ break;
186
+ case "duration":
187
+ r.render = (o) => {
188
+ const c = o || 0, n = s.key === "avgDuration" || s.key === "maxDuration";
189
+ return /* @__PURE__ */ e("span", { className: `ss-dash-duration ${n ? S(c) : ""}`, children: s.key === "totalDuration" ? c.toFixed(1) + "ms" : c.toFixed(2) + "ms" });
190
+ };
191
+ break;
192
+ default:
193
+ s.key === "count" ? r.render = (o) => /* @__PURE__ */ e("span", { style: { color: "var(--ss-muted)", textAlign: "center", display: "block" }, children: o || 0 }) : s.key === "percentOfTotal" && (r.render = (o) => /* @__PURE__ */ e("span", { style: { color: "var(--ss-muted)", textAlign: "center", display: "block" }, children: (o || 0).toFixed(1) + "%" }));
194
+ break;
195
+ }
196
+ return r;
197
+ }
198
+ function se(s, d, i, r, o, c) {
199
+ const n = {
200
+ key: s.key,
201
+ label: s.label,
202
+ width: s.width,
203
+ sortable: s.sortable
204
+ };
205
+ switch (s.type) {
206
+ case "index":
207
+ n.render = (a) => /* @__PURE__ */ e("span", { style: { color: "var(--ss-dim)" }, children: a });
208
+ break;
209
+ case "sql":
210
+ n.render = (a, t) => {
211
+ const p = t.sql || t.sql_text || "", u = t.id;
212
+ return /* @__PURE__ */ l("div", { children: [
213
+ /* @__PURE__ */ e(
214
+ "span",
215
+ {
216
+ className: `ss-dash-sql ${d.has(u) ? "ss-dash-expanded" : ""}`,
217
+ title: "Click to expand",
218
+ onClick: (h) => {
219
+ h.stopPropagation(), o(u);
220
+ },
221
+ role: "button",
222
+ tabIndex: 0,
223
+ onKeyDown: (h) => h.key === "Enter" && o(u),
224
+ children: p
225
+ }
226
+ ),
227
+ (i.get(L(t)) ?? 0) > 1 && /* @__PURE__ */ l("span", { className: "ss-dash-dup", children: [
228
+ "×",
229
+ i.get(L(t))
230
+ ] })
231
+ ] });
232
+ };
233
+ break;
234
+ case "duration":
235
+ n.render = (a) => {
236
+ const t = a || 0;
237
+ return /* @__PURE__ */ e("span", { className: `ss-dash-duration ${S(t)}`, children: t.toFixed(2) + "ms" });
238
+ };
239
+ break;
240
+ case "method":
241
+ n.render = (a, t) => {
242
+ const p = F(t);
243
+ return /* @__PURE__ */ e("span", { className: `ss-dash-method ss-dash-method-${p.toLowerCase()}`, children: p });
244
+ };
245
+ break;
246
+ case "model":
247
+ n.render = (a) => /* @__PURE__ */ e(
248
+ "span",
249
+ {
250
+ style: { color: "var(--ss-muted)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
251
+ title: a,
252
+ children: a || "-"
253
+ }
254
+ );
255
+ break;
256
+ case "connection":
257
+ n.render = (a) => /* @__PURE__ */ e("span", { style: { color: "var(--ss-dim)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: a || "-" });
258
+ break;
259
+ case "time":
260
+ n.render = (a, t) => {
261
+ const p = a || (H(t) ?? "");
262
+ return /* @__PURE__ */ e(J, { ts: p, className: "ss-dash-event-time" });
263
+ };
264
+ break;
265
+ case "explain":
266
+ n.render = (a, t) => {
267
+ if (F(t) !== "select") return null;
268
+ const u = t.id, h = r.get(u), y = h && !h.loading && h.result && !h.error, b = h?.loading;
269
+ return /* @__PURE__ */ e(
270
+ "button",
271
+ {
272
+ type: "button",
273
+ className: `ss-dash-explain-btn${y ? " ss-dash-explain-btn-active" : ""}`,
274
+ onClick: (g) => {
275
+ g.stopPropagation(), c?.(u);
276
+ },
277
+ disabled: !!b,
278
+ children: b ? "..." : "EXPLAIN"
279
+ }
280
+ );
281
+ };
282
+ break;
283
+ }
284
+ return n;
285
+ }
286
+ export {
287
+ de as Q
288
+ };
@@ -0,0 +1,117 @@
1
+ import { jsx as g, jsxs as j } from "react/jsx-runtime";
2
+ import { useState as E, useRef as z, useCallback as s, useEffect as L, useMemo as w } from "react";
3
+ import { QueriesController as T, resolveField as i, computeDashboardQuerySummary as V } from "adonisjs-server-stats/core";
4
+ import { a as q } from "./index-CAUHa8QX.js";
5
+ import { Q as F } from "./QueriesContent-BDIx8zFn.js";
6
+ function O({ options: v = {} }) {
7
+ const [S, u] = E(1), r = z(new T("list")), [h, b] = E(r.current.state), n = s(() => {
8
+ b({ ...r.current.state });
9
+ }, []), { viewMode: a, sort: f, search: x } = h, c = s(
10
+ (e) => {
11
+ e !== r.current.state.viewMode && (r.current.setViewMode(e), u(1), n());
12
+ },
13
+ [n]
14
+ ), D = s(
15
+ (e) => {
16
+ r.current.setSearch(e), n();
17
+ },
18
+ [n]
19
+ );
20
+ L(() => u(1), [x]);
21
+ const Q = a === "grouped" ? "queries/grouped" : "queries", { data: d, meta: p, isLoading: y, getApi: C } = q(Q, {
22
+ ...v,
23
+ page: S,
24
+ search: x,
25
+ sort: f.key,
26
+ sortDir: f.dir
27
+ }), _ = s(
28
+ (e) => {
29
+ r.current.toggleSort(e), n();
30
+ },
31
+ [n]
32
+ ), $ = s(
33
+ (e) => {
34
+ r.current.toggleExpand(e), n();
35
+ },
36
+ [n]
37
+ ), M = s(
38
+ async (e) => {
39
+ const t = r.current.getExplainState(e);
40
+ if (t && !t.loading) {
41
+ r.current.clearExplain(), n();
42
+ return;
43
+ }
44
+ r.current.startExplain(e), n();
45
+ try {
46
+ const o = await C().explainQuery(e);
47
+ o && o.error ? r.current.completeExplain(e, {
48
+ rows: [],
49
+ error: o.error,
50
+ message: o.message
51
+ }) : r.current.completeExplain(e, {
52
+ plan: o?.plan || void 0,
53
+ rows: o?.rows || void 0
54
+ });
55
+ } catch (o) {
56
+ console.warn("[ss] Query explain failed:", o), r.current.failExplain(
57
+ e,
58
+ o instanceof Error ? o.message : String(o)
59
+ );
60
+ }
61
+ n();
62
+ },
63
+ [C, n]
64
+ ), k = s(() => {
65
+ r.current.clearExplain(), n();
66
+ }, [n]), m = a === "grouped" ? d?.groups || [] : d || [], l = w(() => a !== "grouped" ? m : m.map((e) => {
67
+ const t = { ...e };
68
+ return t.sqlNormalized ??= i(e, "sql_normalized", "pattern") ?? void 0, t.count ??= i(e, "total_count"), t.avgDuration ??= i(e, "avg_duration"), t.maxDuration ??= i(e, "max_duration"), t.minDuration ??= i(e, "min_duration"), t.totalDuration ??= i(e, "total_duration"), t.percentOfTotal ??= i(e, "pct_time"), t;
69
+ }), [m, a]), N = w(() => {
70
+ if (a === "grouped")
71
+ return `${l.length} query patterns`;
72
+ const e = V(l, p ?? void 0), t = [`${e.totalCount} queries`];
73
+ return e.slowCount > 0 && t.push(`${e.slowCount} slow`), e.dupCount > 0 && t.push(`${e.dupCount} dup`), t.push(`avg ${(e.avgDuration || 0).toFixed(1)}ms`), t.join(", ");
74
+ }, [a, l, p]);
75
+ return /* @__PURE__ */ g(
76
+ F,
77
+ {
78
+ mode: "dashboard",
79
+ controllerState: h,
80
+ queries: l,
81
+ meta: p,
82
+ isLoading: y && !d,
83
+ onSearchChange: D,
84
+ onSort: _,
85
+ onToggleExpand: $,
86
+ onViewModeChange: c,
87
+ onPageChange: u,
88
+ onExplain: M,
89
+ onCloseExplain: k,
90
+ summary: N,
91
+ filterBarChildren: /* @__PURE__ */ j("div", { className: "ss-dash-btn-group", children: [
92
+ /* @__PURE__ */ g(
93
+ "button",
94
+ {
95
+ type: "button",
96
+ className: `ss-dash-btn ${a === "list" ? "ss-dash-active" : ""}`,
97
+ onClick: () => c("list"),
98
+ children: "List"
99
+ }
100
+ ),
101
+ /* @__PURE__ */ g(
102
+ "button",
103
+ {
104
+ type: "button",
105
+ className: `ss-dash-btn ${a === "grouped" ? "ss-dash-active" : ""}`,
106
+ onClick: () => c("grouped"),
107
+ children: "Grouped"
108
+ }
109
+ )
110
+ ] })
111
+ }
112
+ );
113
+ }
114
+ export {
115
+ O as QueriesSection,
116
+ O as default
117
+ };
@@ -0,0 +1,87 @@
1
+ import { jsx as S, jsxs as w, Fragment as N } from "react/jsx-runtime";
2
+ import { useRef as L, useState as R, useCallback as o, useMemo as l } from "react";
3
+ import { QueriesController as q, filterQueries as z, countDuplicateQueries as A, computeQuerySummary as B, formatDuration as F } from "adonisjs-server-stats/core";
4
+ import { u as M } from "./index-CAUHa8QX.js";
5
+ import { Q as U } from "./QueriesContent-BDIx8zFn.js";
6
+ function P({ options: m }) {
7
+ const { baseUrl: d = "", debugEndpoint: g = "/admin/api/debug", authToken: c } = m || {}, { data: u, isLoading: Q, error: h } = M("queries", m), e = L(new q("list")), [f, b] = R(e.current.state), t = o(() => {
8
+ b({ ...e.current.state });
9
+ }, []), { search: x } = f, y = o(
10
+ (r) => {
11
+ e.current.setSearch(r), t();
12
+ },
13
+ [t]
14
+ ), $ = o(
15
+ (r) => {
16
+ e.current.toggleExpand(r), t();
17
+ },
18
+ [t]
19
+ ), v = o((r) => {
20
+ }, []), D = o(
21
+ async (r) => {
22
+ const C = e.current.getExplainState(r);
23
+ if (C && !C.loading) {
24
+ e.current.clearExplain(), t();
25
+ return;
26
+ }
27
+ e.current.startExplain(r), t();
28
+ try {
29
+ const n = {};
30
+ c && (n.Authorization = `Bearer ${c}`);
31
+ const k = `${d}${g}/queries/${r}/explain`, a = await (await fetch(k, { headers: n })).json();
32
+ a && a.error ? e.current.completeExplain(r, {
33
+ rows: [],
34
+ error: a.error,
35
+ message: a.message
36
+ }) : e.current.completeExplain(r, {
37
+ plan: a?.plan || void 0,
38
+ rows: a?.rows || void 0
39
+ });
40
+ } catch (n) {
41
+ console.warn("[ss] Query explain failed:", n), e.current.failExplain(
42
+ r,
43
+ n instanceof Error ? n.message : String(n)
44
+ );
45
+ }
46
+ t();
47
+ },
48
+ [d, g, c, t]
49
+ ), T = o(() => {
50
+ e.current.clearExplain(), t();
51
+ }, [t]), s = l(() => u?.queries || [], [u]), p = l(() => z(s, x), [s, x]), E = l(() => A(s), [s]), i = l(
52
+ () => B(s, E),
53
+ [s, E]
54
+ );
55
+ if (Q && !u)
56
+ return /* @__PURE__ */ S("div", { className: "ss-dash-empty", children: "Loading queries..." });
57
+ if (h)
58
+ return /* @__PURE__ */ w("div", { className: "ss-dash-empty", children: [
59
+ "Error: ",
60
+ h.message
61
+ ] });
62
+ const j = /* @__PURE__ */ w(N, { children: [
63
+ p.length,
64
+ " queries",
65
+ i.slowCount > 0 && ` | ${i.slowCount} slow`,
66
+ i.dupCount > 0 && ` | ${i.dupCount} dup`,
67
+ p.length > 0 && ` | avg ${F(i.avgDuration)}`
68
+ ] });
69
+ return /* @__PURE__ */ S(
70
+ U,
71
+ {
72
+ mode: "debug",
73
+ controllerState: f,
74
+ queries: p,
75
+ onSearchChange: y,
76
+ onSort: v,
77
+ onToggleExpand: $,
78
+ onExplain: D,
79
+ onCloseExplain: T,
80
+ summary: j
81
+ }
82
+ );
83
+ }
84
+ export {
85
+ P as QueriesTab,
86
+ P as default
87
+ };
@@ -3,8 +3,8 @@ import { useMemo as $, useState as g, useEffect as E, useCallback as L } from "r
3
3
  import { normalizeTraceFields as P, resolveStatusCode as j, resolveDuration as W, durationClassName as z, resolveSpanCount as G, resolveWarningCount as I, resolveTimestamp as U } from "adonisjs-server-stats/core";
4
4
  import { T as Y } from "./TimeAgoCell-o3KigGfM.js";
5
5
  import { u as K } from "./useApiClient-BVtNCmnL.js";
6
- import { a as V, M as D, S as R } from "./index-DwDK-4oX.js";
7
- import { S as H, R as J } from "./SplitPaneWrapper-BiIgT4ND.js";
6
+ import { a as V, M as D, S as R } from "./index-CAUHa8QX.js";
7
+ import { S as H, R as J } from "./SplitPaneWrapper-DyRyH5Re.js";
8
8
  import { D as Q } from "./DataTable-YyShr5B-.js";
9
9
  import { F as X } from "./FilterBar-CQ7bD669.js";
10
10
  import { P as Z } from "./Pagination-BkmzUDY8.js";
@@ -1,6 +1,6 @@
1
1
  import { jsxs as m, jsx as r, Fragment as p } from "react/jsx-runtime";
2
2
  import { useState as y } from "react";
3
- import { a as u, M as f } from "./index-DwDK-4oX.js";
3
+ import { a as u, M as f } from "./index-CAUHa8QX.js";
4
4
  import { D as w } from "./DataTable-YyShr5B-.js";
5
5
  import { F as b } from "./FilterBar-CQ7bD669.js";
6
6
  function A({ options: n = {} }) {
@@ -1,6 +1,6 @@
1
1
  import { jsx as e, jsxs as d } from "react/jsx-runtime";
2
2
  import { useState as g, useMemo as p } from "react";
3
- import { u as b, M as f } from "./index-DwDK-4oX.js";
3
+ import { u as b, M as f } from "./index-CAUHa8QX.js";
4
4
  import { u as w } from "./useResizableTable-CNJmACdt.js";
5
5
  import { F as N } from "./FilterBar-CQ7bD669.js";
6
6
  function R({ options: o, currentPath: n }) {
@@ -1,6 +1,6 @@
1
1
  import { jsxs as c, jsx as l } from "react/jsx-runtime";
2
2
  import { useState as d, useRef as o, useEffect as u } from "react";
3
- import { L as p } from "./LogEntryRow-CMMkqA9M.js";
3
+ import { L as p } from "./LogEntryRow-Bdie9SFe.js";
4
4
  import { initSplitPane as f } from "adonisjs-server-stats/core";
5
5
  function v({ logs: n, onReqIdClick: a }) {
6
6
  const [t, s] = d(null);
@@ -2,11 +2,11 @@ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  import { useState as i, useMemo as q, useEffect as I, useCallback as O } from "react";
3
3
  import { formatDuration as m, durationClassName as j } from "adonisjs-server-stats/core";
4
4
  import { u as U } from "./useApiClient-BVtNCmnL.js";
5
- import { u as W, M as D, S as L } from "./index-DwDK-4oX.js";
5
+ import { u as W, M as D, S as L } from "./index-CAUHa8QX.js";
6
6
  import { T as _ } from "./TimeAgoCell-o3KigGfM.js";
7
7
  import { u as z } from "./useResizableTable-CNJmACdt.js";
8
8
  import { F as G } from "./FilterBar-CQ7bD669.js";
9
- import { S as K, R as V } from "./SplitPaneWrapper-BiIgT4ND.js";
9
+ import { S as K, R as V } from "./SplitPaneWrapper-DyRyH5Re.js";
10
10
  const S = {
11
11
  request: "#1e3a5f",
12
12
  middleware: "rgba(30, 58, 95, 0.7)",
@@ -15,7 +15,7 @@ interface DataTableProps<T> {
15
15
  onSort?: (key: string) => void;
16
16
  onRowClick?: (row: T) => void;
17
17
  rowClassName?: string | ((row: T) => string);
18
- emptyMessage?: string;
18
+ emptyMessage?: React.ReactNode;
19
19
  className?: string;
20
20
  renderAfterRow?: (row: T, index: number) => React.ReactNode;
21
21
  }
@@ -0,0 +1,33 @@
1
+ import { default as React } from 'react';
2
+ import { QueriesControllerState } from '../../../core/queries-controller.js';
3
+ interface QueriesContentProps {
4
+ /** Rendering mode — determines feature set (explain, pagination, grouped). */
5
+ mode: 'dashboard' | 'debug';
6
+ controllerState: QueriesControllerState;
7
+ /** Query rows (untyped dashboard rows or typed QueryRecord[]). */
8
+ queries: Record<string, unknown>[];
9
+ /** Pagination metadata (dashboard only). */
10
+ meta?: {
11
+ page: number;
12
+ lastPage: number;
13
+ total: number;
14
+ } | null;
15
+ isLoading?: boolean;
16
+ onSearchChange: (search: string) => void;
17
+ onSort: (key: string) => void;
18
+ onToggleExpand: (id: number | string) => void;
19
+ onViewModeChange?: (mode: 'list' | 'grouped') => void;
20
+ onPageChange?: (page: number) => void;
21
+ onExplain?: (queryId: number) => void;
22
+ onCloseExplain?: () => void;
23
+ summary: React.ReactNode;
24
+ filterBarChildren?: React.ReactNode;
25
+ }
26
+ /**
27
+ * Shared queries rendering component used by both Dashboard QueriesSection
28
+ * and DebugPanel QueriesTab. Both modes render the same UI — same columns,
29
+ * same styles, same DataTable. The only differences: debug mode has no
30
+ * explain, no pagination, and no grouped view.
31
+ */
32
+ export declare function QueriesContent({ mode, controllerState, queries, meta, isLoading, onSearchChange, onSort, onToggleExpand, onViewModeChange, onPageChange, onExplain, onCloseExplain, summary, filterBarChildren, }: QueriesContentProps): import("react/jsx-runtime").JSX.Element;
33
+ export default QueriesContent;
@@ -435,7 +435,7 @@ function A({
435
435
  }
436
436
  );
437
437
  }
438
- const ge = L(() => import("./QueriesTab-x85PjkyS.js")), me = L(() => import("./EventsTab-B-FoehXC.js")), ve = L(() => import("./EmailsTab-Ch8jp10B.js")), fe = L(() => import("./RoutesTab-CbzBOzpc.js")), we = L(() => import("./LogsTab-CS4sLfLw.js")), ke = L(() => import("./TimelineTab-Ue9tUD_n.js")), Ne = L(() => import("./CacheTab-DOhuK05d.js")), ye = L(() => import("./JobsTab-DqnifQXV.js")), Ce = L(() => import("./ConfigTab-C8kriE2b.js")), Se = L(() => import("./InternalsTab-CkEKpRMU.js")), Le = L(() => import("./CustomPaneTab-CvzQS_Wh.js"));
438
+ const ge = L(() => import("./QueriesTab-C7CCwhVc.js")), me = L(() => import("./EventsTab-DF13BChE.js")), ve = L(() => import("./EmailsTab-BITuGTQm.js")), fe = L(() => import("./RoutesTab-CbQECiUc.js")), we = L(() => import("./LogsTab-DYSpL637.js")), ke = L(() => import("./TimelineTab-BKTFbsPe.js")), Ne = L(() => import("./CacheTab-D8js5o69.js")), ye = L(() => import("./JobsTab-DK8Fl9nz.js")), Ce = L(() => import("./ConfigTab-CDvljuBF.js")), Se = L(() => import("./InternalsTab--RD-L1dX.js")), Le = L(() => import("./CustomPaneTab-Db9eIQ-9.js"));
439
439
  function Qe(s) {
440
440
  const {
441
441
  defaultOpen: o = !1,
@@ -724,7 +724,7 @@ const De = [
724
724
  "jobs",
725
725
  "config",
726
726
  "internals"
727
- ], Re = L(() => import("./OverviewSection-CxvfOR0v.js")), Oe = L(() => import("./RequestsSection-DETN9oZb.js")), _e = L(() => import("./QueriesSection-CrMdU5Ax.js")), je = L(() => import("./EventsSection-DJPwHeT8.js")), Pe = L(() => import("./RoutesSection-CmorkJeC.js")), He = L(() => import("./LogsSection-C1xC5aP4.js")), qe = L(() => import("./EmailsSection-BJyFJf7A.js")), Ue = L(() => import("./CacheSection-BYN53kYO.js")), Fe = L(() => import("./JobsSection-DWF4i1t_.js")), Ae = L(() => import("./ConfigSection-B9EHh4Rp.js")), ze = L(() => import("./InternalsSection-B6VlVx5f.js"));
727
+ ], Re = L(() => import("./OverviewSection-CuaccMZt.js")), Oe = L(() => import("./RequestsSection-mENyeNsk.js")), _e = L(() => import("./QueriesSection-CvGGh5Ij.js")), je = L(() => import("./EventsSection-7mDZv70I.js")), Pe = L(() => import("./RoutesSection-DjovlaNS.js")), He = L(() => import("./LogsSection-CrWqxWRr.js")), qe = L(() => import("./EmailsSection-D7oxvAjA.js")), Ue = L(() => import("./CacheSection-DZFOiOYH.js")), Fe = L(() => import("./JobsSection-B_VJFWy6.js")), Ae = L(() => import("./ConfigSection-DoJmvNkF.js")), ze = L(() => import("./InternalsSection-BwrTfpjA.js"));
728
728
  function Xe(s) {
729
729
  const {
730
730
  baseUrl: o = "",
@@ -1,4 +1,4 @@
1
- import { B as s, D as t, c as r, J as u, M as g, d as o, d, S as D, T as S, e as h, a as B, u as T, f as b, g as l, h as m } from "./index-DwDK-4oX.js";
1
+ import { B as s, D as t, c as r, J as u, M as g, d as o, d, S as D, T as S, e as h, a as B, u as T, f as b, g as l, h as m } from "./index-CAUHa8QX.js";
2
2
  export {
3
3
  s as Badge,
4
4
  t as DashboardPage,