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,42 @@
1
+ /**
2
+ * Describes a single column in a queries table.
3
+ */
4
+ export interface QueriesColumnDef {
5
+ /** Field key used to look up the value from a row. */
6
+ key: string;
7
+ /** Header label displayed in the `<th>`. */
8
+ label: string;
9
+ /** Optional fixed width (CSS value). */
10
+ width?: string;
11
+ /** Whether the column supports click-to-sort. */
12
+ sortable?: boolean;
13
+ /**
14
+ * Semantic type hint that the rendering layer can use to pick the
15
+ * appropriate cell formatter / component.
16
+ */
17
+ type?: 'sql' | 'duration' | 'method' | 'model' | 'time' | 'index' | 'connection' | 'explain';
18
+ }
19
+ /**
20
+ * Return the 6 columns used in the debug-pane queries tab.
21
+ *
22
+ * Columns: #, SQL, Duration, Method, Model, Time.
23
+ */
24
+ export declare function getDebugPaneColumns(): QueriesColumnDef[];
25
+ /**
26
+ * Return the columns used in the dashboard list view.
27
+ *
28
+ * Columns: #, SQL, Duration, Method, Model, Connection, Time, and
29
+ * optionally an Explain button column.
30
+ *
31
+ * @param opts.showExplain - Whether to include the Explain button column
32
+ * (default `true`).
33
+ */
34
+ export declare function getDashboardListColumns(opts?: {
35
+ showExplain?: boolean;
36
+ }): QueriesColumnDef[];
37
+ /**
38
+ * Return the columns used in the dashboard grouped view.
39
+ *
40
+ * Columns: SQL (Pattern), Count, Avg, Min, Max, Total, % Time.
41
+ */
42
+ export declare function getDashboardGroupedColumns(): QueriesColumnDef[];
@@ -0,0 +1,94 @@
1
+ import { PlanNode } from './explain-utils.js';
2
+ /**
3
+ * Result of an EXPLAIN query.
4
+ */
5
+ export interface ExplainResult {
6
+ /** Parsed plan nodes (JSON EXPLAIN format). */
7
+ plan?: PlanNode[];
8
+ /** Raw row objects (plain EXPLAIN format). */
9
+ rows?: Record<string, unknown>[];
10
+ /** Error message from the server. */
11
+ error?: string;
12
+ /** Additional message from the server. */
13
+ message?: string;
14
+ }
15
+ /**
16
+ * Per-query EXPLAIN loading / result state.
17
+ */
18
+ export interface ExplainEntry {
19
+ loading: boolean;
20
+ result?: ExplainResult;
21
+ error?: string;
22
+ }
23
+ /**
24
+ * Complete state shape managed by {@link QueriesController}.
25
+ */
26
+ export interface QueriesControllerState {
27
+ /** Current view mode: individual queries or grouped patterns. */
28
+ viewMode: 'list' | 'grouped';
29
+ /** Active sort column and direction. */
30
+ sort: {
31
+ key: string;
32
+ dir: 'asc' | 'desc';
33
+ };
34
+ /** Set of expanded row IDs (for SQL expand/collapse). */
35
+ expandedIds: Set<number | string>;
36
+ /** EXPLAIN state keyed by query ID. */
37
+ explainData: Map<number, ExplainEntry>;
38
+ /** Current search / filter string. */
39
+ search: string;
40
+ }
41
+ /**
42
+ * A framework-agnostic headless controller that manages pure state for
43
+ * the queries panel.
44
+ *
45
+ * Every mutation method returns the updated state object so that
46
+ * framework wrappers can trigger a re-render.
47
+ */
48
+ export declare class QueriesController {
49
+ state: QueriesControllerState;
50
+ constructor(initialViewMode?: 'list' | 'grouped');
51
+ /**
52
+ * Switch between list and grouped view.
53
+ *
54
+ * Resets sort, expanded IDs, EXPLAIN data, and search.
55
+ */
56
+ setViewMode(mode: 'list' | 'grouped'): QueriesControllerState;
57
+ /**
58
+ * Toggle sort on a column. If the column is already sorted, flips
59
+ * direction; otherwise sorts descending on the new column.
60
+ */
61
+ toggleSort(key: string): QueriesControllerState;
62
+ /**
63
+ * Toggle the expanded state of a row by its ID.
64
+ */
65
+ toggleExpand(id: number | string): QueriesControllerState;
66
+ /**
67
+ * Check whether a row is currently expanded.
68
+ */
69
+ isExpanded(id: number | string): boolean;
70
+ /**
71
+ * Update the search string.
72
+ */
73
+ setSearch(search: string): QueriesControllerState;
74
+ /**
75
+ * Mark a query as loading its EXPLAIN plan.
76
+ */
77
+ startExplain(queryId: number): void;
78
+ /**
79
+ * Store a successful EXPLAIN result for a query.
80
+ */
81
+ completeExplain(queryId: number, result: ExplainResult): void;
82
+ /**
83
+ * Store an EXPLAIN error for a query.
84
+ */
85
+ failExplain(queryId: number, error: string): void;
86
+ /**
87
+ * Clear all EXPLAIN data.
88
+ */
89
+ clearExplain(): void;
90
+ /**
91
+ * Get the current EXPLAIN state for a specific query.
92
+ */
93
+ getExplainState(queryId: number): ExplainEntry | undefined;
94
+ }
@@ -12,6 +12,23 @@ export interface QuerySummary {
12
12
  /** Total number of queries considered. */
13
13
  totalCount: number;
14
14
  }
15
+ /**
16
+ * A normalized query record with consistent camelCase field names.
17
+ *
18
+ * Used to convert untyped API responses (which may use snake_case) into
19
+ * a clean typed object.
20
+ */
21
+ export interface NormalizedQuery {
22
+ id: number | string;
23
+ sql: string;
24
+ sqlNormalized: string;
25
+ duration: number;
26
+ method: string;
27
+ model: string;
28
+ connection: string;
29
+ timestamp: string | number;
30
+ inTransaction: boolean;
31
+ }
15
32
  /**
16
33
  * Filter queries by a search term.
17
34
  *
@@ -32,3 +49,35 @@ export declare function countDuplicateQueries(queries: QueryRecord[]): Record<st
32
49
  * @param dupCounts – the duplicate-count map returned by {@link countDuplicateQueries}
33
50
  */
34
51
  export declare function computeQuerySummary(queries: QueryRecord[], dupCounts: Record<string, number>): QuerySummary;
52
+ /**
53
+ * Compute summary statistics from untyped dashboard API query records.
54
+ *
55
+ * Uses field-resolvers to extract duration values from `Record<string, unknown>`
56
+ * rows, making it work with both snake_case and camelCase API responses.
57
+ *
58
+ * @param queries - Untyped query rows from the dashboard API.
59
+ * @param meta - Optional pagination meta with the total count.
60
+ */
61
+ export declare function computeDashboardQuerySummary(queries: Record<string, unknown>[], meta?: {
62
+ total?: number;
63
+ }): QuerySummary;
64
+ /**
65
+ * Normalize an untyped dashboard API query row to a clean typed object.
66
+ *
67
+ * Handles both snake_case and camelCase field names using field-resolvers.
68
+ *
69
+ * @param row - An untyped row from the dashboard queries API.
70
+ */
71
+ export declare function normalizeDashboardQuery(row: Record<string, unknown>): NormalizedQuery;
72
+ /**
73
+ * Build a map counting how many times each SQL pattern appears.
74
+ *
75
+ * Works with both typed `QueryRecord[]` and untyped dashboard rows.
76
+ * Uses `sqlNormalized` (or `sql` as fallback) as the grouping key.
77
+ *
78
+ * @param queries - Array of query objects with at least `sqlNormalized` or `sql`.
79
+ */
80
+ export declare function buildSqlCounts(queries: Array<{
81
+ sqlNormalized?: string;
82
+ sql?: string;
83
+ } | Record<string, unknown>>): Map<string, number>;
@@ -69,6 +69,8 @@ export interface DiagnosticsResponse {
69
69
  available?: boolean;
70
70
  mode?: string;
71
71
  }>;
72
+ /** Lucid connections that have debug: true. Empty means no query events will be emitted. */
73
+ lucidDebugConnections?: string[];
72
74
  storage: {
73
75
  ready: boolean;
74
76
  dbPath: string;
@@ -1,7 +1,7 @@
1
1
  import { jsxs as o, jsx as t } from "react/jsx-runtime";
2
2
  import { useState as c, useCallback as k } from "react";
3
3
  import { formatCacheSize as x, formatTtl as D } from "adonisjs-server-stats/core";
4
- import { a as N, J as V } from "./index-DwDK-4oX.js";
4
+ import { a as N, J as V } from "./index-CAUHa8QX.js";
5
5
  import { C as L } from "./CacheStatsBar-CRodCOeP.js";
6
6
  import { D as F } from "./DataTable-YyShr5B-.js";
7
7
  import { F as T } from "./FilterBar-CQ7bD669.js";
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  import { useState as u, useMemo as T, useCallback as z } from "react";
3
3
  import { formatTtl as K, formatCacheSize as L } from "adonisjs-server-stats/core";
4
4
  import { u as R } from "./useDashboardApiBase-Bi36pJ2L.js";
5
- import { u as $, J as j } from "./index-DwDK-4oX.js";
5
+ import { u as $, J as j } from "./index-CAUHa8QX.js";
6
6
  import { u as A } from "./useResizableTable-CNJmACdt.js";
7
7
  import { C as F } from "./CacheStatsBar-CRodCOeP.js";
8
8
  import { F as D } from "./FilterBar-CQ7bD669.js";
@@ -1,5 +1,5 @@
1
1
  import { jsx as t } from "react/jsx-runtime";
2
- import { a as i } from "./index-DwDK-4oX.js";
2
+ import { a as i } from "./index-CAUHa8QX.js";
3
3
  import { C as n } from "./ConfigContent-CnsEI4j3.js";
4
4
  function m({ options: o = {} }) {
5
5
  const { data: a, isLoading: s } = i("config", o);
@@ -1,6 +1,6 @@
1
1
  import { jsxs as i, jsx as n } from "react/jsx-runtime";
2
2
  import { u as f } from "./useDashboardApiBase-Bi36pJ2L.js";
3
- import { u as m } from "./index-DwDK-4oX.js";
3
+ import { u as m } from "./index-CAUHa8QX.js";
4
4
  import { C as d } from "./ConfigContent-CnsEI4j3.js";
5
5
  function b({ options: r, dashboardPath: o }) {
6
6
  const { resolvedOptions: a } = f(o, r), { data: e, isLoading: t, error: s } = m("config", a);
@@ -1,7 +1,7 @@
1
1
  import { jsxs as l, jsx as r } from "react/jsx-runtime";
2
2
  import { useState as w, useMemo as f } from "react";
3
3
  import { compactPreview as k, formatDuration as x, durationClassName as M } from "adonisjs-server-stats/core";
4
- import { u as L, B as A, M as B } from "./index-DwDK-4oX.js";
4
+ import { u as L, B as A, M as B } from "./index-CAUHa8QX.js";
5
5
  import { T as b } from "./TimeAgoCell-o3KigGfM.js";
6
6
  import { u as D } from "./useResizableTable-CNJmACdt.js";
7
7
  import { F as P } from "./FilterBar-CQ7bD669.js";
@@ -2,7 +2,7 @@ import { jsx as s, jsxs as y, Fragment as P } from "react/jsx-runtime";
2
2
  import { useState as l, useEffect as T, useCallback as j } from "react";
3
3
  import { resolveCcAddr as N, resolveToAddr as f, resolveFromAddr as b, resolveAttachmentCount as F, resolveTimestamp as _ } from "adonisjs-server-stats/core";
4
4
  import { T as $ } from "./TimeAgoCell-o3KigGfM.js";
5
- import { a as D } from "./index-DwDK-4oX.js";
5
+ import { a as D } from "./index-CAUHa8QX.js";
6
6
  import { D as E } from "./DataTable-YyShr5B-.js";
7
7
  import { F as O } from "./FilterBar-CQ7bD669.js";
8
8
  import { E as B } from "./EmailPreviewOverlay-BmXOAvqG.js";
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as r } from "react/jsx-runtime";
2
2
  import { useState as c, useMemo as f, useCallback as w } from "react";
3
3
  import { resolveTimestamp as k } from "adonisjs-server-stats/core";
4
4
  import { T as E } from "./TimeAgoCell-o3KigGfM.js";
5
- import { u as S } from "./index-DwDK-4oX.js";
5
+ import { u as S } from "./index-CAUHa8QX.js";
6
6
  import { u as j } from "./useResizableTable-CNJmACdt.js";
7
7
  import { F as q } from "./FilterBar-CQ7bD669.js";
8
8
  import { E as $ } from "./EmailPreviewOverlay-BmXOAvqG.js";
@@ -2,7 +2,7 @@ import { jsxs as i, jsx as e, Fragment as g } from "react/jsx-runtime";
2
2
  import { useState as m, useEffect as f } from "react";
3
3
  import { resolveEventName as y, resolveTimestamp as u } from "adonisjs-server-stats/core";
4
4
  import { T as w } from "./TimeAgoCell-o3KigGfM.js";
5
- import { a as b, J as N } from "./index-DwDK-4oX.js";
5
+ import { a as b, J as N } from "./index-CAUHa8QX.js";
6
6
  import { D as x } from "./DataTable-YyShr5B-.js";
7
7
  import { F as P } from "./FilterBar-CQ7bD669.js";
8
8
  import { P as k } from "./Pagination-BkmzUDY8.js";
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  import { useState as p, useMemo as u } from "react";
3
3
  import { resolveTimestamp as g } from "adonisjs-server-stats/core";
4
4
  import { T as b } from "./TimeAgoCell-o3KigGfM.js";
5
- import { u as f, J as v } from "./index-DwDK-4oX.js";
5
+ import { u as f, J as v } from "./index-CAUHa8QX.js";
6
6
  import { u as w } from "./useResizableTable-CNJmACdt.js";
7
7
  import { F as y } from "./FilterBar-CQ7bD669.js";
8
8
  function E({ options: c }) {