adonisjs-server-stats 1.12.0 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +19 -1
  2. package/dist/core/api-client.d.ts +1 -1
  3. package/dist/core/index.js +1 -1
  4. package/dist/react/{CacheSection-DZFOiOYH.js → CacheSection-CX2duJuc.js} +1 -1
  5. package/dist/react/{CacheTab-D8js5o69.js → CacheTab-CgT4t0oZ.js} +1 -1
  6. package/dist/react/{ConfigSection-DoJmvNkF.js → ConfigSection-Dt0FyeaW.js} +1 -1
  7. package/dist/react/{ConfigTab-CDvljuBF.js → ConfigTab-KtiTtsrj.js} +1 -1
  8. package/dist/react/{CustomPaneTab-Db9eIQ-9.js → CustomPaneTab-15QoEplP.js} +1 -1
  9. package/dist/react/{EmailsTab-BITuGTQm.js → EmailsTab-CUjubln_.js} +2 -2
  10. package/dist/react/{EventsSection-7mDZv70I.js → EventsSection-GGPoYSNv.js} +1 -1
  11. package/dist/react/{EventsTab-DF13BChE.js → EventsTab-Wdwr0_ny.js} +1 -1
  12. package/dist/react/{JobsSection-B_VJFWy6.js → JobsSection-BqqIh_DR.js} +1 -1
  13. package/dist/react/{JobsTab-DK8Fl9nz.js → JobsTab-CBrU-ryL.js} +1 -1
  14. package/dist/react/{LogEntryRow-Bdie9SFe.js → LogEntryRow-BOrRkhRU.js} +1 -1
  15. package/dist/react/{LogsSection-CrWqxWRr.js → LogsSection-Cm_lphM6.js} +2 -2
  16. package/dist/react/{LogsTab-DYSpL637.js → LogsTab-jKwv9G7Q.js} +2 -2
  17. package/dist/react/{OverviewSection-CuaccMZt.js → OverviewSection-XF7bakyM.js} +1 -1
  18. package/dist/react/QueriesSection-DsQBKrNK.js +123 -0
  19. package/dist/react/QueriesTab-CxCC1GVq.js +87 -0
  20. package/dist/react/{RequestsSection-mENyeNsk.js → RequestsSection-D8cMbZU0.js} +2 -2
  21. package/dist/react/{RoutesSection-DjovlaNS.js → RoutesSection-D0y5JQP4.js} +1 -1
  22. package/dist/react/{RoutesTab-CbQECiUc.js → RoutesTab-Y_alJVMV.js} +1 -1
  23. package/dist/react/{SplitPaneWrapper-DyRyH5Re.js → SplitPaneWrapper-CZl1ouIT.js} +1 -1
  24. package/dist/react/{TimelineTab-BKTFbsPe.js → TimelineTab-HyqZpfbp.js} +2 -2
  25. package/dist/react/{index-CAUHa8QX.js → index-CsprmgzI.js} +2 -2
  26. package/dist/react/index.js +1 -1
  27. package/dist/src/edge/client/dashboard.js +2 -2
  28. package/dist/src/edge/client/debug-panel-deferred.js +1 -1
  29. package/dist/src/edge/client/stats-bar.js +1 -1
  30. package/dist/src/edge/client-vue/dashboard.js +3 -3
  31. package/dist/src/edge/client-vue/debug-panel-deferred.js +1 -1
  32. package/dist/src/edge/client-vue/stats-bar.js +1 -1
  33. package/dist/src/provider/auth_middleware_detector.d.ts +12 -6
  34. package/dist/src/provider/auth_middleware_detector.js +53 -6
  35. package/dist/src/provider/boot_helpers.d.ts +1 -0
  36. package/dist/src/provider/boot_helpers.js +7 -1
  37. package/dist/src/provider/server_stats_provider.js +2 -1
  38. package/dist/src/routes/no_session_middleware.d.ts +14 -0
  39. package/dist/src/routes/no_session_middleware.js +16 -0
  40. package/dist/src/routes/register_routes.js +5 -1
  41. package/dist/vue/{CacheSection-Bx41lpfK.js → CacheSection-DRqV3YX2.js} +1 -1
  42. package/dist/vue/{ConfigSection-fkfUdCmx.js → ConfigSection-C6pQCHAL.js} +1 -1
  43. package/dist/vue/{EmailsSection-CbcDKF9Q.js → EmailsSection-BTNw3ZU2.js} +1 -1
  44. package/dist/vue/{EmailsTab-CNyEODVB.js → EmailsTab-CwIF1fik.js} +1 -1
  45. package/dist/vue/{EventsSection-CWbTYOBi.js → EventsSection-BpgkWIwM.js} +1 -1
  46. package/dist/vue/{JobsSection-CGGO6rtS.js → JobsSection-DrghFEKL.js} +1 -1
  47. package/dist/vue/{LogsSection-BPB-C-XA.js → LogsSection-BDxx9Bfi.js} +1 -1
  48. package/dist/vue/{OverviewSection-BTcnPeoM.js → OverviewSection-BAgZTPjY.js} +1 -1
  49. package/dist/vue/{QueriesSection-2SE3igQJ.js → QueriesSection-CUpwhp7u.js} +127 -115
  50. package/dist/vue/{RequestsSection-DXcG5Zok.js → RequestsSection-D8P2xpF2.js} +1 -1
  51. package/dist/vue/{RoutesSection-BkNGWdoP.js → RoutesSection-0qB81hTT.js} +1 -1
  52. package/dist/vue/{index-CptF6Qbp.js → index-30jLw-_w.js} +2 -2
  53. package/dist/vue/index.js +1 -1
  54. package/package.json +1 -1
  55. package/dist/react/QueriesSection-CvGGh5Ij.js +0 -117
  56. package/dist/react/QueriesTab-C7CCwhVc.js +0 -87
  57. package/dist/react/{EmailsSection-D7oxvAjA.js → EmailsSection-YcJYR5eA.js} +1 -1
@@ -10,39 +10,53 @@ function isAuthMiddleware(importPath) {
10
10
  importPath.includes('silent_auth') ||
11
11
  importPath.includes('silentAuth'));
12
12
  }
13
+ /**
14
+ * Check if an import path refers to session middleware.
15
+ */
16
+ function isSessionMiddleware(importPath) {
17
+ return importPath.includes('session');
18
+ }
13
19
  /**
14
20
  * Extract import paths from a `server.use([...])` or `router.use([...])`
15
- * block that match auth-related middleware.
21
+ * block that match the given predicate.
16
22
  */
17
- function extractAuthImportsFromBlock(block) {
23
+ function extractMatchingImportsFromBlock(block, predicate) {
18
24
  const importRegex = /import\(\s*['"]([^'"]+)['"]\s*\)/g;
19
25
  const results = [];
20
26
  let importMatch;
21
27
  while ((importMatch = importRegex.exec(block)) !== null) {
22
28
  const importPath = importMatch[1];
23
- if (isAuthMiddleware(importPath)) {
29
+ if (predicate(importPath)) {
24
30
  results.push(importPath);
25
31
  }
26
32
  }
27
33
  return results;
28
34
  }
29
35
  /**
30
- * Parse source code and detect auth-related middleware
36
+ * Parse source code and detect middleware matching a predicate
31
37
  * in `server.use()` or `router.use()` blocks.
32
38
  *
33
39
  * This is a pure function that operates on source text.
34
40
  */
35
- export function detectAuthMiddlewareInSource(source) {
41
+ function detectMiddlewareInSource(source, predicate) {
36
42
  if (!source)
37
43
  return [];
38
44
  const found = [];
39
45
  const useBlockRegex = /(?:server|router)\.use\(\s*\[([\s\S]*?)\]\s*\)/g;
40
46
  let match;
41
47
  while ((match = useBlockRegex.exec(source)) !== null) {
42
- found.push(...extractAuthImportsFromBlock(match[1]));
48
+ found.push(...extractMatchingImportsFromBlock(match[1], predicate));
43
49
  }
44
50
  return found;
45
51
  }
52
+ /** Detect auth-related middleware in source text. */
53
+ export function detectAuthMiddlewareInSource(source) {
54
+ return detectMiddlewareInSource(source, isAuthMiddleware);
55
+ }
56
+ /** Detect session middleware in source text. */
57
+ export function detectSessionMiddlewareInSource(source) {
58
+ return detectMiddlewareInSource(source, isSessionMiddleware);
59
+ }
46
60
  /**
47
61
  * Read the kernel source from disk, trying `.ts` then `.js` extensions.
48
62
  */
@@ -71,6 +85,18 @@ export function detectGlobalAuthMiddleware(makePath) {
71
85
  return [];
72
86
  }
73
87
  }
88
+ /**
89
+ * Read `start/kernel.{ts,js}` from the app root and detect global session
90
+ * middleware. Returns an empty array if the file cannot be read.
91
+ */
92
+ export function detectGlobalSessionMiddleware(makePath) {
93
+ try {
94
+ return detectSessionMiddlewareInSource(readKernelSource(makePath));
95
+ }
96
+ catch {
97
+ return [];
98
+ }
99
+ }
74
100
  /**
75
101
  * Build the warning message lines for detected auth middleware.
76
102
  */
@@ -95,3 +121,24 @@ export function buildAuthMiddlewareWarning(found, dimFn, boldFn) {
95
121
  dimFn('router.group(() => { ... }).use(middleware.silentAuth())'),
96
122
  ];
97
123
  }
124
+ /**
125
+ * Build the warning message lines for detected session middleware.
126
+ */
127
+ export function buildSessionMiddlewareWarning(found, dimFn, boldFn) {
128
+ return [
129
+ ...found.map((m) => dimFn('→') + ' ' + m),
130
+ '',
131
+ dimFn('server-stats routes are polled every ~3s. global session middleware'),
132
+ dimFn('issues a Set-Cookie on every response, which can accumulate cookies'),
133
+ dimFn('and eventually break the browser.'),
134
+ '',
135
+ dimFn('server-stats already strips Set-Cookie headers from its own routes,'),
136
+ dimFn('but for best results, move session middleware to a named route group:'),
137
+ '',
138
+ boldFn('// start/kernel.ts — remove from router.use()'),
139
+ dimFn("// () => import('@adonisjs/session/session_middleware')"),
140
+ '',
141
+ boldFn('// start/routes.ts — add to your route groups instead'),
142
+ dimFn("router.group(() => { ... }).use(middleware.session())"),
143
+ ];
144
+ }
@@ -17,4 +17,5 @@ export declare function collectRegisteredPaths(statsEndpoint: string | false, de
17
17
  export declare function checkDashboardDeps(appImport: (name: string) => Promise<unknown>): Promise<string[]>;
18
18
  export declare function logMissingDeps(missing: string[]): void;
19
19
  export declare function warnAboutAuthMiddleware(config: ResolvedServerStatsConfig, makePath: (dir: string, file: string) => string): void;
20
+ export declare function warnAboutSessionMiddleware(makePath: (dir: string, file: string) => string): void;
20
21
  export declare function logDashboardError(category: 'missing-dep' | 'timeout' | 'unknown', err: unknown): void;
@@ -1,5 +1,5 @@
1
1
  import { log, dim, bold } from '../utils/logger.js';
2
- import { detectGlobalAuthMiddleware, buildAuthMiddlewareWarning, } from './auth_middleware_detector.js';
2
+ import { detectGlobalAuthMiddleware, detectGlobalSessionMiddleware, buildAuthMiddlewareWarning, buildSessionMiddlewareWarning, } from './auth_middleware_detector.js';
3
3
  export function deriveEndpointPaths(endpoint, devToolbar) {
4
4
  const statsEndpoint = typeof endpoint === 'string' ? endpoint : false;
5
5
  const debugEndpoint = devToolbar?.enabled
@@ -57,6 +57,12 @@ export function warnAboutAuthMiddleware(config, makePath) {
57
57
  return;
58
58
  log.block(bold('found global auth middleware that will run on every poll:'), buildAuthMiddlewareWarning(found, dim, bold));
59
59
  }
60
+ export function warnAboutSessionMiddleware(makePath) {
61
+ const found = detectGlobalSessionMiddleware(makePath);
62
+ if (found.length === 0)
63
+ return;
64
+ log.block(bold('found global session middleware that affects server-stats routes:'), buildSessionMiddlewareWarning(found, dim, bold));
65
+ }
60
66
  export function logDashboardError(category, err) {
61
67
  if (category === 'missing-dep') {
62
68
  log.block('Dashboard could not start — missing dependencies. Install with:', [
@@ -2,7 +2,7 @@ import { StatsEngine } from '../engine/stats_engine.js';
2
2
  import { setShouldShow, setExcludedPrefixes } from '../middleware/request_tracking_middleware.js';
3
3
  import { registerAllRoutes } from '../routes/register_routes.js';
4
4
  import { log, dim, setVerbose } from '../utils/logger.js';
5
- import { deriveEndpointPaths, computeDashboardPath, collectRegisteredPaths, warnAboutAuthMiddleware, } from './boot_helpers.js';
5
+ import { deriveEndpointPaths, computeDashboardPath, collectRegisteredPaths, warnAboutAuthMiddleware, warnAboutSessionMiddleware, } from './boot_helpers.js';
6
6
  import { resolveToolbarConfig, buildExcludedPrefixes } from './dashboard_setup.js';
7
7
  import { buildDiagnostics } from './diagnostics.js';
8
8
  import { hookPinoToLogStream, setupLogStreamBroadcast, setupStatsIntervalHelper, checkDashboardDepsHelper, registerEdgePluginHelper, setupNonWebBridgeHelper, setupDevToolbarCore, applyToolbarResult, } from './provider_helpers_extra.js';
@@ -101,6 +101,7 @@ export default class ServerStatsProvider {
101
101
  return;
102
102
  log.list('routes auto-registered (no manual setup needed):', paths);
103
103
  warnAboutAuthMiddleware(config, this.app.makePath.bind(this.app));
104
+ warnAboutSessionMiddleware(this.app.makePath.bind(this.app));
104
105
  }
105
106
  async ready() {
106
107
  const config = this.app.config.get('server_stats');
@@ -0,0 +1,14 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ /**
3
+ * Middleware that strips `Set-Cookie` headers from the response.
4
+ *
5
+ * AdonisJS session middleware (when registered globally via `router.use()`)
6
+ * issues a `Set-Cookie` on every request — even stateless API endpoints.
7
+ * Because this package's routes are polled every few seconds, this causes
8
+ * rapid cookie accumulation that can break the browser.
9
+ *
10
+ * This middleware runs after the route handler (and any global middleware)
11
+ * and removes the `Set-Cookie` header so sessions are never started by
12
+ * server-stats routes.
13
+ */
14
+ export declare function noSessionMiddleware(ctx: HttpContext, next: () => Promise<void>): Promise<void>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Middleware that strips `Set-Cookie` headers from the response.
3
+ *
4
+ * AdonisJS session middleware (when registered globally via `router.use()`)
5
+ * issues a `Set-Cookie` on every request — even stateless API endpoints.
6
+ * Because this package's routes are polled every few seconds, this causes
7
+ * rapid cookie accumulation that can break the browser.
8
+ *
9
+ * This middleware runs after the route handler (and any global middleware)
10
+ * and removes the `Set-Cookie` header so sessions are never started by
11
+ * server-stats routes.
12
+ */
13
+ export async function noSessionMiddleware(ctx, next) {
14
+ await next();
15
+ ctx.response.response.removeHeader('set-cookie');
16
+ }
@@ -1,12 +1,16 @@
1
1
  import { createAccessMiddleware } from './access_middleware.js';
2
2
  import { registerDashboardRoutes } from './dashboard_routes.js';
3
3
  import { registerDebugRoutes } from './debug_routes.js';
4
+ import { noSessionMiddleware } from './no_session_middleware.js';
4
5
  import { registerStatsRoute } from './stats_routes.js';
5
6
  /**
6
7
  * Register all server-stats routes in a single call.
7
8
  */
8
9
  export function registerAllRoutes(options) {
9
- const middleware = options.shouldShow ? [createAccessMiddleware(options.shouldShow)] : [];
10
+ const middleware = [
11
+ noSessionMiddleware,
12
+ ...(options.shouldShow ? [createAccessMiddleware(options.shouldShow)] : []),
13
+ ];
10
14
  if (typeof options.statsEndpoint === 'string') {
11
15
  registerStatsRoute(options.router, options.statsEndpoint, options.getStatsController, middleware);
12
16
  }
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as E, inject as v, ref as h, computed as C, openBlock as a, createElementBlock as l, createElementVNode as e, toDisplayString as c, createCommentVNode as g, createVNode as F, unref as y, Fragment as N, renderList as A, withModifiers as B, createBlock as U } from "vue";
2
- import { u as H } from "./index-CptF6Qbp.js";
2
+ import { u as H } from "./index-30jLw-_w.js";
3
3
  import { u as M } from "./useResizableTable-BoivAevK.js";
4
4
  import { DashboardApi as j, formatCacheSize as q, formatTtl as I } from "adonisjs-server-stats/core";
5
5
  import { u as G } from "./useApiClient-BQQ9CF-q.js";
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as re, inject as m, ref as w, computed as x, openBlock as i, createElementBlock as r, createElementVNode as n, normalizeClass as a, createCommentVNode as b, Fragment as _, toDisplayString as u, unref as c, renderList as A, withModifiers as I, normalizeStyle as R } from "vue";
2
- import { u as ue } from "./index-CptF6Qbp.js";
2
+ import { u as ue } from "./index-30jLw-_w.js";
3
3
  import { isRedactedValue as d, flattenConfig as z, TAB_ICONS as g, countLeaves as ce, collectTopLevelObjectKeys as pe, copyWithFeedback as de, formatFlatValue as ve } from "adonisjs-server-stats/core";
4
4
  const fe = { style: { position: "relative", flex: 1 } }, he = ["value"], ge = ["title", "onClick"], ye = ["viewBox", "innerHTML"], be = ["viewBox", "innerHTML"], $e = ["onClick"], we = { key: 0 }, xe = ["title", "onClick"], ke = ["viewBox", "innerHTML"], Ce = ["viewBox", "innerHTML"], _e = ["onClick"], Se = { key: 0 }, Be = { style: { padding: "4px 16px", fontSize: "10px", color: "var(--ss-muted)" } }, Le = ["onClick"], He = ["title"], Te = ["title"], je = ["title", "onClick"], Me = ["viewBox", "innerHTML"], me = ["viewBox", "innerHTML"], Ae = ["onClick"], Ie = ["title", "onClick"], Ee = ["viewBox", "innerHTML"], Ve = ["viewBox", "innerHTML"], Oe = {
5
5
  key: 1,
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as V, inject as h, ref as f, computed as A, openBlock as o, createElementBlock as i, createElementVNode as e, Fragment as c, createTextVNode as u, toDisplayString as n, createCommentVNode as y, normalizeClass as _, createVNode as F, unref as r, renderList as B, createBlock as D } from "vue";
2
2
  import { formatTime as R, timeAgo as z } from "adonisjs-server-stats/core";
3
- import { u as L } from "./index-CptF6Qbp.js";
3
+ import { u as L } from "./index-30jLw-_w.js";
4
4
  import { u as M } from "./useResizableTable-BoivAevK.js";
5
5
  import { _ as U } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
6
6
  import { _ as q } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
@@ -56,7 +56,7 @@ const F = { style: { position: "relative", height: "100%" } }, P = {
56
56
  d.authToken && (s.Authorization = `Bearer ${d.authToken}`);
57
57
  const u = await fetch(`${e}/emails/${l.id}/preview`, {
58
58
  headers: s,
59
- credentials: d.authToken ? "omit" : "include"
59
+ credentials: d.authToken ? "omit" : "same-origin"
60
60
  });
61
61
  u.ok && (r.value = await u.text());
62
62
  } catch {
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as E, inject as i, ref as p, computed as P, openBlock as s, createElementBlock as l, createVNode as v, unref as a, Fragment as h, createElementVNode as e, renderList as T, toDisplayString as c, createBlock as C, createCommentVNode as D } from "vue";
2
2
  import { formatTime as S, timeAgo as V } from "adonisjs-server-stats/core";
3
- import { u as $ } from "./index-CptF6Qbp.js";
3
+ import { u as $ } from "./index-30jLw-_w.js";
4
4
  import { u as A } from "./useResizableTable-BoivAevK.js";
5
5
  import { _ as B } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
6
6
  import { _ as R } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as L, inject as h, ref as p, computed as g, openBlock as o, createElementBlock as d, createElementVNode as s, toDisplayString as n, createCommentVNode as v, createVNode as k, unref as a, withCtx as z, Fragment as _, renderList as x, normalizeClass as w, withModifiers as K, createBlock as M } from "vue";
2
2
  import { extractJobs as O, extractJobStats as Q, JOB_STATUS_FILTERS as W, getJobStatusBadgeColor as q, formatDuration as G, formatTime as H, timeAgo as X } from "adonisjs-server-stats/core";
3
- import { u as Y } from "./index-CptF6Qbp.js";
3
+ import { u as Y } from "./index-30jLw-_w.js";
4
4
  import { u as Z } from "./useResizableTable-BoivAevK.js";
5
5
  import { _ as I } from "./JsonViewer.vue_vue_type_script_setup_true_lang-Bid05zpm.js";
6
6
  import { _ as j } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
@@ -1,7 +1,7 @@
1
1
  import { defineComponent as ie, inject as C, ref as u, computed as B, openBlock as a, createElementBlock as o, createVNode as O, unref as s, withCtx as ue, createElementVNode as n, Fragment as q, renderList as x, normalizeClass as $, toDisplayString as i, withKeys as V, createCommentVNode as _, createStaticVNode as re, createTextVNode as w, withModifiers as U, createBlock as de } from "vue";
2
2
  import { LOG_LEVELS as ce, getStructuredData as m, getLogLevelCssClass as ve, resolveLogLevel as W, resolveLogTimestamp as F, formatTime as pe, timeAgo as he, resolveLogRequestId as g, resolveLogMessage as _e } from "adonisjs-server-stats/core";
3
3
  import { _ as fe } from "./JsonViewer.vue_vue_type_script_setup_true_lang-Bid05zpm.js";
4
- import { u as me } from "./index-CptF6Qbp.js";
4
+ import { u as me } from "./index-30jLw-_w.js";
5
5
  import { _ as ge } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
6
6
  import { _ as ye } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
7
7
  const ke = { class: "ss-dash-log-filters" }, be = ["onClick"], Ce = ["value"], qe = { class: "ss-dash-structured-search" }, $e = ["value"], Fe = ["value"], Le = ["value"], Se = {
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as ws, openBlock as o, createElementBlock as n, Fragment as _, renderList as k, createElementVNode as s, normalizeClass as b, toDisplayString as r, inject as P, ref as D, watch as fs, computed as d, onUnmounted as Ws, unref as x, createVNode as N, createCommentVNode as v, normalizeStyle as ts, createTextVNode as gs } from "vue";
2
2
  import { formatDuration as F, formatTime as Os, timeAgo as Hs, durationClassName as Ks } from "adonisjs-server-stats/core";
3
- import { u as xs, _ as U } from "./index-CptF6Qbp.js";
3
+ import { u as xs, _ as U } from "./index-30jLw-_w.js";
4
4
  const Gs = { class: "ss-dash-btn-group" }, Xs = ["onClick"], Ys = /* @__PURE__ */ ws({
5
5
  __name: "TimeRangeSelector",
6
6
  props: {