adonisjs-server-stats 1.4.0 → 1.5.1

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 (83) hide show
  1. package/README.md +114 -116
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/src/controller/debug_controller.d.ts +2 -2
  4. package/dist/src/controller/debug_controller.d.ts.map +1 -1
  5. package/dist/src/controller/server_stats_controller.d.ts +1 -1
  6. package/dist/src/controller/server_stats_controller.d.ts.map +1 -1
  7. package/dist/src/dashboard/chart_aggregator.d.ts.map +1 -1
  8. package/dist/src/dashboard/chart_aggregator.js +8 -8
  9. package/dist/src/dashboard/dashboard_controller.d.ts +12 -97
  10. package/dist/src/dashboard/dashboard_controller.d.ts.map +1 -1
  11. package/dist/src/dashboard/dashboard_controller.js +244 -522
  12. package/dist/src/dashboard/dashboard_routes.d.ts.map +1 -1
  13. package/dist/src/dashboard/dashboard_routes.js +7 -2
  14. package/dist/src/dashboard/dashboard_store.d.ts +6 -3
  15. package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
  16. package/dist/src/dashboard/dashboard_store.js +54 -78
  17. package/dist/src/dashboard/integrations/cache_inspector.d.ts.map +1 -1
  18. package/dist/src/dashboard/integrations/queue_inspector.d.ts.map +1 -1
  19. package/dist/src/dashboard/migrator.d.ts.map +1 -1
  20. package/dist/src/dashboard/migrator.js +3 -1
  21. package/dist/src/dashboard/models/stats_event.d.ts +1 -1
  22. package/dist/src/dashboard/models/stats_event.d.ts.map +1 -1
  23. package/dist/src/dashboard/models/stats_query.d.ts +1 -1
  24. package/dist/src/dashboard/models/stats_query.d.ts.map +1 -1
  25. package/dist/src/dashboard/models/stats_request.d.ts +2 -2
  26. package/dist/src/dashboard/models/stats_request.d.ts.map +1 -1
  27. package/dist/src/dashboard/models/stats_request.js +1 -1
  28. package/dist/src/dashboard/models/stats_trace.d.ts +1 -1
  29. package/dist/src/dashboard/models/stats_trace.d.ts.map +1 -1
  30. package/dist/src/debug/debug_store.d.ts +6 -6
  31. package/dist/src/debug/debug_store.d.ts.map +1 -1
  32. package/dist/src/debug/debug_store.js +10 -10
  33. package/dist/src/debug/email_collector.d.ts +0 -9
  34. package/dist/src/debug/email_collector.d.ts.map +1 -1
  35. package/dist/src/debug/email_collector.js +6 -28
  36. package/dist/src/debug/event_collector.d.ts +1 -1
  37. package/dist/src/debug/event_collector.d.ts.map +1 -1
  38. package/dist/src/debug/event_collector.js +17 -17
  39. package/dist/src/debug/query_collector.d.ts +1 -1
  40. package/dist/src/debug/query_collector.d.ts.map +1 -1
  41. package/dist/src/debug/query_collector.js +13 -14
  42. package/dist/src/debug/ring_buffer.d.ts.map +1 -1
  43. package/dist/src/debug/route_inspector.d.ts +1 -1
  44. package/dist/src/debug/route_inspector.d.ts.map +1 -1
  45. package/dist/src/debug/route_inspector.js +12 -12
  46. package/dist/src/debug/trace_collector.d.ts.map +1 -1
  47. package/dist/src/debug/trace_collector.js +6 -5
  48. package/dist/src/edge/client/dashboard.css +516 -171
  49. package/dist/src/edge/client/dashboard.js +2756 -1662
  50. package/dist/src/edge/client/debug-panel.css +476 -133
  51. package/dist/src/edge/client/debug-panel.js +1496 -1043
  52. package/dist/src/edge/client/stats-bar.css +64 -30
  53. package/dist/src/edge/client/stats-bar.js +598 -319
  54. package/dist/src/edge/plugin.d.ts +1 -1
  55. package/dist/src/edge/plugin.d.ts.map +1 -1
  56. package/dist/src/edge/plugin.js +41 -59
  57. package/dist/src/edge/views/stats-bar.edge +1 -1
  58. package/dist/src/index.d.ts +1 -1
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/middleware/request_tracking_middleware.d.ts +4 -4
  61. package/dist/src/middleware/request_tracking_middleware.d.ts.map +1 -1
  62. package/dist/src/middleware/request_tracking_middleware.js +7 -6
  63. package/dist/src/prometheus/prometheus_collector.d.ts +1 -1
  64. package/dist/src/prometheus/prometheus_collector.d.ts.map +1 -1
  65. package/dist/src/provider/server_stats_provider.d.ts +1 -1
  66. package/dist/src/provider/server_stats_provider.d.ts.map +1 -1
  67. package/dist/src/provider/server_stats_provider.js +31 -31
  68. package/dist/src/utils/json_helpers.d.ts +8 -0
  69. package/dist/src/utils/json_helpers.d.ts.map +1 -0
  70. package/dist/src/utils/json_helpers.js +21 -0
  71. package/dist/src/utils/mail_helpers.d.ts +13 -0
  72. package/dist/src/utils/mail_helpers.d.ts.map +1 -0
  73. package/dist/src/utils/mail_helpers.js +26 -0
  74. package/dist/src/utils/math_helpers.d.ts +8 -0
  75. package/dist/src/utils/math_helpers.d.ts.map +1 -0
  76. package/dist/src/utils/math_helpers.js +11 -0
  77. package/dist/src/utils/time_helpers.d.ts +12 -0
  78. package/dist/src/utils/time_helpers.d.ts.map +1 -0
  79. package/dist/src/utils/time_helpers.js +32 -0
  80. package/dist/src/utils/transmit_client.d.ts +9 -0
  81. package/dist/src/utils/transmit_client.d.ts.map +1 -0
  82. package/dist/src/utils/transmit_client.js +20 -0
  83. package/package.json +35 -29
@@ -1,4 +1,4 @@
1
- import type { ServerStatsConfig } from "../types.js";
1
+ import type { ServerStatsConfig } from '../types.js';
2
2
  /**
3
3
  * Edge plugin that registers the `@serverStats()` tag.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/edge/plugin.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA0BrD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,IACrD,MAAM,GAAG,UAoIlB"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/edge/plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAKpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,IACrD,MAAM,GAAG,UAmHlB"}
@@ -1,26 +1,10 @@
1
- import { readFileSync } from "node:fs";
2
- import { createRequire } from "node:module";
3
- import { dirname, join } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { Template } from "edge.js";
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { Template } from 'edge.js';
5
+ import { loadTransmitClient } from '../utils/transmit_client.js';
6
6
  const DIR = dirname(fileURLToPath(import.meta.url));
7
- const read = (rel) => readFileSync(join(DIR, rel), "utf-8");
8
- /**
9
- * Try to locate and read the @adonisjs/transmit-client build file.
10
- * Returns the file contents wrapped to expose `window.Transmit`, or
11
- * an empty string if the package is not installed.
12
- */
13
- function loadTransmitClient() {
14
- try {
15
- const req = createRequire(join(process.cwd(), "package.json"));
16
- const clientPath = req.resolve("@adonisjs/transmit-client/build/index.js");
17
- const src = readFileSync(clientPath, "utf-8");
18
- return `(function(){var __exports={};(function(){${src.replace(/^export\s*\{[^}]*\}\s*;?\s*$/m, "")}\n__exports.Transmit=Transmit;})();window.Transmit=__exports.Transmit;})()`;
19
- }
20
- catch {
21
- return "";
22
- }
23
- }
7
+ const read = (rel) => readFileSync(join(DIR, rel), 'utf-8');
24
8
  /**
25
9
  * Edge plugin that registers the `@serverStats()` tag.
26
10
  *
@@ -43,64 +27,62 @@ function loadTransmitClient() {
43
27
  export function edgePluginServerStats(config) {
44
28
  return (edge) => {
45
29
  // Mount Edge views under the `ss` disk (needed for @include resolution)
46
- edge.mount("ss", join(DIR, "views"));
30
+ edge.mount('ss', join(DIR, 'views'));
47
31
  // Read client assets once at boot
48
- const css = read("client/stats-bar.css");
49
- const js = read("client/stats-bar.js");
50
- const endpoint = typeof config.endpoint === "string"
51
- ? config.endpoint
52
- : "/admin/api/server-stats";
32
+ const css = read('client/stats-bar.css');
33
+ const js = read('client/stats-bar.js');
34
+ const endpoint = typeof config.endpoint === 'string' ? config.endpoint : '/admin/api/server-stats';
53
35
  const intervalMs = config.intervalMs || 3000;
54
36
  const showDebug = !!config.devToolbar?.enabled;
55
37
  // Badge groups for the Edge template
56
38
  const groups = [
57
39
  // Process
58
40
  [
59
- { id: "node", label: "NODE" },
60
- { id: "up", label: "UP" },
61
- { id: "cpu", label: "CPU" },
62
- { id: "evt", label: "EVT" },
41
+ { id: 'node', label: 'NODE' },
42
+ { id: 'up', label: 'UP' },
43
+ { id: 'cpu', label: 'CPU' },
44
+ { id: 'evt', label: 'EVT' },
63
45
  ],
64
46
  // Memory
65
47
  [
66
- { id: "mem", label: "HEAP" },
67
- { id: "rss", label: "RSS" },
68
- { id: "sys", label: "SYS" },
48
+ { id: 'mem', label: 'HEAP' },
49
+ { id: 'rss', label: 'RSS' },
50
+ { id: 'sys', label: 'SYS' },
69
51
  ],
70
52
  // HTTP
71
53
  [
72
- { id: "rps", label: "REQ/s" },
73
- { id: "avg", label: "AVG" },
74
- { id: "err", label: "ERR" },
75
- { id: "conn", label: "CONN" },
54
+ { id: 'rps', label: 'REQ/s' },
55
+ { id: 'avg', label: 'AVG' },
56
+ { id: 'err', label: 'ERR' },
57
+ { id: 'conn', label: 'CONN' },
76
58
  ],
77
59
  // DB
78
- [{ id: "db", label: "DB" }],
60
+ [{ id: 'db', label: 'DB' }],
79
61
  // Redis
80
62
  [
81
- { id: "redis", label: "REDIS" },
82
- { id: "rmem", label: "MEM" },
83
- { id: "rkeys", label: "KEYS" },
84
- { id: "rhit", label: "HIT" },
63
+ { id: 'redis', label: 'REDIS' },
64
+ { id: 'rmem', label: 'MEM' },
65
+ { id: 'rkeys', label: 'KEYS' },
66
+ { id: 'rhit', label: 'HIT' },
85
67
  ],
86
68
  // Queue
87
69
  [
88
- { id: "q", label: "Q" },
89
- { id: "workers", label: "WORKERS" },
70
+ { id: 'q', label: 'Q' },
71
+ { id: 'workers', label: 'WORKERS' },
90
72
  ],
91
73
  // App
92
74
  [
93
- { id: "users", label: "USERS" },
94
- { id: "hooks", label: "HOOKS" },
95
- { id: "mail", label: "MAIL" },
75
+ { id: 'users', label: 'USERS' },
76
+ { id: 'hooks', label: 'HOOKS' },
77
+ { id: 'mail', label: 'MAIL' },
96
78
  ],
97
79
  // Logs
98
80
  [
99
- { id: "logerr", label: "LOG ERR" },
100
- { id: "lograte", label: "LOG/m" },
81
+ { id: 'logerr', label: 'LOG ERR' },
82
+ { id: 'lograte', label: 'LOG/m' },
101
83
  ],
102
84
  // Debug (conditional)
103
- ...(showDebug ? [[{ id: "dbg-queries", label: "QRY" }]] : []),
85
+ ...(showDebug ? [[{ id: 'dbg-queries', label: 'QRY' }]] : []),
104
86
  ];
105
87
  const state = {
106
88
  css,
@@ -111,25 +93,25 @@ export function edgePluginServerStats(config) {
111
93
  groups,
112
94
  };
113
95
  if (showDebug) {
114
- state.debugCss = read("client/debug-panel.css");
115
- state.debugJs = read("client/debug-panel.js");
116
- state.logsEndpoint = "/admin/api/debug/logs";
96
+ state.debugCss = read('client/debug-panel.css');
97
+ state.debugJs = read('client/debug-panel.js');
98
+ state.logsEndpoint = '/admin/api/debug/logs';
117
99
  state.customPanes = config.devToolbar?.panes || [];
118
100
  state.showTracing = !!config.devToolbar?.tracing;
119
101
  state.dashboardPath = config.devToolbar?.dashboard
120
- ? (config.devToolbar.dashboardPath || '/__stats')
102
+ ? config.devToolbar.dashboardPath || '/__stats'
121
103
  : null;
122
- state.transmitClient = loadTransmitClient();
104
+ state.transmitClient = loadTransmitClient(join(process.cwd(), 'package.json'));
123
105
  }
124
106
  // Pre-render via Template directly — bypasses edge.createRenderer() which
125
107
  // would re-run #executePlugins and cause infinite recursion.
126
108
  const template = new Template(edge.compiler, edge.globals, {}, edge.processor);
127
- const html = template.render("ss::stats-bar", state);
109
+ const html = template.render('ss::stats-bar', state);
128
110
  const escaped = JSON.stringify(html);
129
111
  // Track whether shouldShow is configured (controls render-time guard)
130
112
  const hasShouldShow = !!config.shouldShow;
131
113
  edge.registerTag({
132
- tagName: "serverStats",
114
+ tagName: 'serverStats',
133
115
  block: false,
134
116
  seekable: true,
135
117
  compile(_parser, buffer, token) {
@@ -5,7 +5,7 @@
5
5
  <div id="ss-bar" class="ss-bar" data-endpoint="{{ endpoint }}" data-interval="{{ intervalMs }}">
6
6
  <div class="ss-bar-left">
7
7
  @if(showDebug)
8
- <button type="button" id="ss-dbg-wrench" class="ss-dbg-btn" title="Open debug panel">🔍</button>
8
+ <button type="button" id="ss-dbg-wrench" class="ss-dbg-btn" title="Open debug panel">🔍 Open debug panel</button>
9
9
  @end
10
10
  <div id="ss-dot" class="ss-dot"></div>
11
11
  </div>
@@ -4,7 +4,7 @@ export { RequestMetrics } from './engine/request_metrics.js';
4
4
  export { trace } from './debug/trace_collector.js';
5
5
  export { DashboardStore } from './dashboard/dashboard_store.js';
6
6
  export type { MetricCollector } from './collectors/collector.js';
7
- export type { MetricValue, ServerStats, ServerStatsConfig, LogStats, DevToolbarOptions } from './types.js';
7
+ export type { MetricValue, ServerStats, ServerStatsConfig, LogStats, DevToolbarOptions, } from './types.js';
8
8
  export type { DebugPane, DebugPaneColumn, DebugPaneFormatType, DebugPaneSearch, BadgeColor, QueryRecord, EventRecord, EmailRecord, RouteRecord, TraceSpan, TraceRecord, DevToolbarConfig, } from './debug/types.js';
9
9
  export type { RequestFilters, QueryFilters, EventFilters, EmailFilters, LogFilters, TraceFilters, PaginatedResult, } from './dashboard/dashboard_store.js';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC1G,YAAY,EACV,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,gCAAgC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAChE,YAAY,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,GAClB,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,gCAAgC,CAAA"}
@@ -1,7 +1,7 @@
1
- import type { HttpContext } from "@adonisjs/core/http";
2
- import type { NextFn } from "@adonisjs/core/types/http";
3
- import type { TraceCollector } from "../debug/trace_collector.js";
4
- import type { TraceRecord } from "../debug/types.js";
1
+ import type { TraceCollector } from '../debug/trace_collector.js';
2
+ import type { TraceRecord } from '../debug/types.js';
3
+ import type { HttpContext } from '@adonisjs/core/http';
4
+ import type { NextFn } from '@adonisjs/core/types/http';
5
5
  /**
6
6
  * Returns true if the current async context is inside an excluded request
7
7
  * (e.g. a debug panel polling request). Used by collectors to skip
@@ -1 +1 @@
1
- {"version":3,"file":"request_tracking_middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/request_tracking_middleware.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAOD,wBAAgB,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,IAAI,QAE/D;AAOD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,QAEjE;AAQD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,QAEnD;AASD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAErD;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAQD,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC,GAAG,IAAI,QAGjD;AAED,MAAM,CAAC,OAAO,OAAO,yBAAyB;IACtC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM;CAsE5C"}
1
+ {"version":3,"file":"request_tracking_middleware.d.ts","sourceRoot":"","sources":["../../../src/middleware/request_tracking_middleware.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AASvD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAOD,wBAAgB,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,IAAI,QAE/D;AAOD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,QAEjE;AAQD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,QAEnD;AASD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAErD;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,WAAW,CAAA;CACpB;AAQD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,CAAC,GAAG,IAAI,QAEpF;AAED,MAAM,CAAC,OAAO,OAAO,yBAAyB;IACtC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM;CAuE5C"}
@@ -1,6 +1,6 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import { performance } from "node:perf_hooks";
3
- import { getRequestMetrics } from "../collectors/http_collector.js";
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { performance } from 'node:perf_hooks';
3
+ import { getRequestMetrics } from '../collectors/http_collector.js';
4
4
  /**
5
5
  * AsyncLocalStorage that marks the current request as "excluded" from
6
6
  * debug collection. Checked by QueryCollector and EventCollector to
@@ -70,7 +70,8 @@ export default class RequestTrackingMiddleware {
70
70
  // runs BEFORE router middleware like initialize_auth_middleware and
71
71
  // silentAuth — so ctx.auth isn't populated yet. The function is called
72
72
  // at Edge render time (inside the controller), when auth is available.
73
- if (shouldShowFn && typeof ctx.view?.share === "function") {
73
+ if (shouldShowFn && typeof ctx.view?.share === 'function') {
74
+ ;
74
75
  ctx.view.share({
75
76
  __ssShowFn: () => {
76
77
  try {
@@ -85,8 +86,8 @@ export default class RequestTrackingMiddleware {
85
86
  // Skip tracing and dashboard persistence for the debug panel's own requests
86
87
  // (e.g. /admin/api/debug/*, /admin/api/server-stats) so they don't flood
87
88
  // the timeline. HTTP metrics (req/s, avg latency) are still recorded.
88
- const skipTracing = excludedPrefixes.length > 0
89
- && excludedPrefixes.some((prefix) => requestUrl.startsWith(prefix));
89
+ const skipTracing = excludedPrefixes.length > 0 &&
90
+ excludedPrefixes.some((prefix) => requestUrl.startsWith(prefix));
90
91
  const runRequest = async () => {
91
92
  try {
92
93
  await next();
@@ -1,5 +1,5 @@
1
- import type { ConfigProvider } from '@adonisjs/core/types';
2
1
  import type { ServerStats } from '../types.js';
2
+ import type { ConfigProvider } from '@adonisjs/core/types';
3
3
  export declare function serverStatsCollector(): ConfigProvider<any>;
4
4
  export declare const ServerStatsCollector: {
5
5
  instance: {
@@ -1 +1 @@
1
- {"version":3,"file":"prometheus_collector.d.ts","sourceRoot":"","sources":["../../../src/prometheus/prometheus_collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,wBAAgB,oBAAoB,IAAI,cAAc,CAAC,GAAG,CAAC,CA4M1D;AAED,eAAO,MAAM,oBAAoB,EAAE;IAAE,QAAQ,EAAE;QAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CAElG,CAAA"}
1
+ {"version":3,"file":"prometheus_collector.d.ts","sourceRoot":"","sources":["../../../src/prometheus/prometheus_collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,wBAAgB,oBAAoB,IAAI,cAAc,CAAC,GAAG,CAAC,CA6M1D;AAED,eAAO,MAAM,oBAAoB,EAAE;IACjC,QAAQ,EAAE;QAAE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CAG/D,CAAA"}
@@ -1,4 +1,4 @@
1
- import type { ApplicationService } from "@adonisjs/core/types";
1
+ import type { ApplicationService } from '@adonisjs/core/types';
2
2
  export default class ServerStatsProvider {
3
3
  protected app: ApplicationService;
4
4
  private intervalId;
@@ -1 +1 @@
1
- {"version":3,"file":"server_stats_provider.d.ts","sourceRoot":"","sources":["../../../src/provider/server_stats_provider.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAY1B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAX7C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,OAAO,CAAC,uBAAuB,CAA+C;IAC9E,OAAO,CAAC,mBAAmB,CAA8C;IACzE,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAA+C;gBAE3C,GAAG,EAAE,kBAAkB;IAEvC,IAAI;IAuCJ,KAAK;YAoFG,eAAe;IAqF7B;;;;;;OAMG;YACW,cAAc;IA4GtB,QAAQ;CAwCf"}
1
+ {"version":3,"file":"server_stats_provider.d.ts","sourceRoot":"","sources":["../../../src/provider/server_stats_provider.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAY1B,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAX7C,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,uBAAuB,CAA8C;IAC7E,OAAO,CAAC,mBAAmB,CAA6C;IACxE,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,UAAU,CAA8C;gBAE1C,GAAG,EAAE,kBAAkB;IAEvC,IAAI;IAkCJ,KAAK;YA8EG,eAAe;IAmF7B;;;;;;OAMG;YACW,cAAc;IAoGtB,QAAQ;CAwCf"}
@@ -1,9 +1,9 @@
1
- import { StatsEngine } from "../engine/stats_engine.js";
2
- import { DebugStore } from "../debug/debug_store.js";
3
- import { DashboardStore } from "../dashboard/dashboard_store.js";
4
- import { LogStreamService } from "../log_stream/log_stream_service.js";
5
- import { setShouldShow, setTraceCollector, setDashboardPath, setExcludedPrefixes, setOnRequestComplete, } from "../middleware/request_tracking_middleware.js";
6
- import { registerDashboardRoutes } from "../dashboard/dashboard_routes.js";
1
+ import { registerDashboardRoutes } from '../dashboard/dashboard_routes.js';
2
+ import { DashboardStore } from '../dashboard/dashboard_store.js';
3
+ import { DebugStore } from '../debug/debug_store.js';
4
+ import { StatsEngine } from '../engine/stats_engine.js';
5
+ import { LogStreamService } from '../log_stream/log_stream_service.js';
6
+ import { setShouldShow, setTraceCollector, setDashboardPath, setExcludedPrefixes, setOnRequestComplete, } from '../middleware/request_tracking_middleware.js';
7
7
  export default class ServerStatsProvider {
8
8
  app;
9
9
  intervalId = null;
@@ -20,7 +20,7 @@ export default class ServerStatsProvider {
20
20
  this.app = app;
21
21
  }
22
22
  async boot() {
23
- const config = this.app.config.get("server_stats");
23
+ const config = this.app.config.get('server_stats');
24
24
  if (!config)
25
25
  return;
26
26
  // Wire up the per-request shouldShow callback
@@ -32,7 +32,7 @@ export default class ServerStatsProvider {
32
32
  const toolbarConfig = config.devToolbar;
33
33
  if (toolbarConfig?.enabled && toolbarConfig.dashboard && !this.app.inProduction) {
34
34
  try {
35
- const router = await this.app.container.make("router");
35
+ const router = await this.app.container.make('router');
36
36
  const dashPath = toolbarConfig.dashboardPath ?? '/__stats';
37
37
  registerDashboardRoutes(router, dashPath, () => this.dashboardController, config.shouldShow);
38
38
  }
@@ -43,8 +43,8 @@ export default class ServerStatsProvider {
43
43
  if (!this.app.usingEdgeJS)
44
44
  return;
45
45
  try {
46
- const edge = await import("edge.js");
47
- const { edgePluginServerStats } = await import("../edge/plugin.js");
46
+ const edge = await import('edge.js');
47
+ const { edgePluginServerStats } = await import('../edge/plugin.js');
48
48
  edge.default.use(edgePluginServerStats(config));
49
49
  }
50
50
  catch {
@@ -52,14 +52,13 @@ export default class ServerStatsProvider {
52
52
  }
53
53
  }
54
54
  async ready() {
55
- const config = this.app.config.get("server_stats");
55
+ const config = this.app.config.get('server_stats');
56
56
  if (!config)
57
57
  return;
58
58
  if (this.app.inTest && config.skipInTest !== false)
59
59
  return;
60
60
  this.engine = new StatsEngine(config.collectors);
61
- // Bind engine to container so the controller can access it
62
- this.app.container.singleton("server_stats.engine", () => this.engine);
61
+ this.app.container.singleton('server_stats.engine', () => this.engine);
63
62
  await this.engine.start();
64
63
  // Dev toolbar setup
65
64
  const toolbarConfig = config.devToolbar;
@@ -89,9 +88,9 @@ export default class ServerStatsProvider {
89
88
  }
90
89
  }
91
90
  let transmit = null;
92
- if (config.transport === "transmit") {
91
+ if (config.transport === 'transmit') {
93
92
  try {
94
- transmit = await this.app.container.make("transmit");
93
+ transmit = await this.app.container.make('transmit');
95
94
  }
96
95
  catch {
97
96
  // Transmit not installed — skip broadcasting
@@ -99,7 +98,7 @@ export default class ServerStatsProvider {
99
98
  }
100
99
  let prometheusCollector = null;
101
100
  try {
102
- const mod = await import("../prometheus/prometheus_collector.js");
101
+ const mod = await import('../prometheus/prometheus_collector.js');
103
102
  prometheusCollector = mod.ServerStatsCollector.instance;
104
103
  }
105
104
  catch {
@@ -123,19 +122,19 @@ export default class ServerStatsProvider {
123
122
  }
124
123
  async setupDevToolbar(toolbarConfig) {
125
124
  this.debugStore = new DebugStore(toolbarConfig);
126
- // Bind debug store to container
127
- this.app.container.singleton("debug.store", () => this.debugStore);
125
+ this.app.container.singleton('debug.store', () => this.debugStore);
128
126
  // Load persisted data before starting collectors
129
127
  if (toolbarConfig.persistDebugData) {
130
- this.persistPath = typeof toolbarConfig.persistDebugData === 'string'
131
- ? this.app.makePath(toolbarConfig.persistDebugData)
132
- : this.app.makePath('.adonisjs', 'server-stats', 'debug-data.json');
128
+ this.persistPath =
129
+ typeof toolbarConfig.persistDebugData === 'string'
130
+ ? this.app.makePath(toolbarConfig.persistDebugData)
131
+ : this.app.makePath('.adonisjs', 'server-stats', 'debug-data.json');
133
132
  await this.debugStore.loadFromDisk(this.persistPath);
134
133
  }
135
134
  // Get the emitter
136
135
  let emitter = null;
137
136
  try {
138
- emitter = await this.app.container.make("emitter");
137
+ emitter = await this.app.container.make('emitter');
139
138
  }
140
139
  catch {
141
140
  // Emitter not available
@@ -143,7 +142,7 @@ export default class ServerStatsProvider {
143
142
  // Get the router
144
143
  let router = null;
145
144
  try {
146
- router = await this.app.container.make("router");
145
+ router = await this.app.container.make('router');
147
146
  }
148
147
  catch {
149
148
  // Router not available
@@ -167,13 +166,13 @@ export default class ServerStatsProvider {
167
166
  // ── Transmit broadcasting for debug panel live updates ────────
168
167
  let debugTransmit = null;
169
168
  try {
170
- debugTransmit = await this.app.container.make("transmit");
169
+ debugTransmit = await this.app.container.make('transmit');
171
170
  }
172
171
  catch {
173
172
  // Transmit not installed — debug panel will use polling
174
173
  }
175
174
  if (debugTransmit) {
176
- const debugChannel = "server-stats/debug";
175
+ const debugChannel = 'server-stats/debug';
177
176
  const pendingTypes = new Set();
178
177
  this.debugStore.onNewItem((type) => {
179
178
  // Debounce: coalesce rapid events into a single broadcast
@@ -224,14 +223,15 @@ export default class ServerStatsProvider {
224
223
  throw err;
225
224
  }
226
225
  // Bind to container
227
- this.app.container.singleton("dashboard.store", () => this.dashboardStore);
226
+ ;
227
+ this.app.container.singleton('dashboard.store', () => this.dashboardStore);
228
228
  // Set dashboard path in middleware for self-exclusion
229
229
  setDashboardPath(toolbarConfig.dashboardPath);
230
230
  // Create the controller — this makes the routes registered in boot() functional
231
- const DashboardControllerClass = (await import("../dashboard/dashboard_controller.js")).default;
231
+ const DashboardControllerClass = (await import('../dashboard/dashboard_controller.js')).default;
232
232
  this.dashboardController = new DashboardControllerClass(this.dashboardStore, this.debugStore, this.app);
233
233
  // ── Log piping ────────────────────────────────────────────────
234
- const logPath = this.app.makePath("logs", "adonisjs.log");
234
+ const logPath = this.app.makePath('logs', 'adonisjs.log');
235
235
  this.dashboardLogStream = new LogStreamService(logPath, (entry) => {
236
236
  this.dashboardStore?.recordLog(entry);
237
237
  });
@@ -271,18 +271,18 @@ export default class ServerStatsProvider {
271
271
  // ── Transmit streaming for real-time dashboard updates ────────
272
272
  let transmit = null;
273
273
  try {
274
- transmit = await this.app.container.make("transmit");
274
+ transmit = await this.app.container.make('transmit');
275
275
  }
276
276
  catch {
277
277
  // Transmit not installed — skip real-time updates
278
278
  }
279
279
  if (transmit) {
280
- const dashChannel = "server-stats/dashboard";
280
+ const dashChannel = 'server-stats/dashboard';
281
281
  this.dashboardBroadcastTimer = setInterval(async () => {
282
282
  try {
283
283
  if (!dashStore.isReady())
284
284
  return;
285
- const overview = await dashStore.getOverviewMetrics("1h");
285
+ const overview = await dashStore.getOverviewMetrics('1h');
286
286
  transmit.broadcast(dashChannel, overview);
287
287
  }
288
288
  catch {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared JSON parsing utilities with safe fallbacks.
3
+ */
4
+ /** Safely parse a JSON string, returning the original value on failure. */
5
+ export declare function safeParseJson(value: any): any;
6
+ /** Safely parse a JSON string expected to be an array, returning [] on failure. */
7
+ export declare function safeParseJsonArray(value: any): any[];
8
+ //# sourceMappingURL=json_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json_helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/json_helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAQ7C;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,CAGpD"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Shared JSON parsing utilities with safe fallbacks.
3
+ */
4
+ /** Safely parse a JSON string, returning the original value on failure. */
5
+ export function safeParseJson(value) {
6
+ if (value === null || value === undefined)
7
+ return null;
8
+ if (typeof value !== 'string')
9
+ return value;
10
+ try {
11
+ return JSON.parse(value);
12
+ }
13
+ catch {
14
+ return value;
15
+ }
16
+ }
17
+ /** Safely parse a JSON string expected to be an array, returning [] on failure. */
18
+ export function safeParseJsonArray(value) {
19
+ const parsed = safeParseJson(value);
20
+ return Array.isArray(parsed) ? parsed : [];
21
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared email address extraction utilities.
3
+ */
4
+ /**
5
+ * Normalize various AdonisJS mail address formats to a comma-separated string.
6
+ *
7
+ * Handles:
8
+ * - A string: `"user@example.com"`
9
+ * - An object: `{ address: "user@example.com", name: "User" }`
10
+ * - An array of strings or objects
11
+ */
12
+ export declare function extractAddresses(value: any): string;
13
+ //# sourceMappingURL=mail_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail_helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/mail_helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAWnD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Shared email address extraction utilities.
3
+ */
4
+ /**
5
+ * Normalize various AdonisJS mail address formats to a comma-separated string.
6
+ *
7
+ * Handles:
8
+ * - A string: `"user@example.com"`
9
+ * - An object: `{ address: "user@example.com", name: "User" }`
10
+ * - An array of strings or objects
11
+ */
12
+ export function extractAddresses(value) {
13
+ if (!value)
14
+ return '';
15
+ if (typeof value === 'string')
16
+ return value;
17
+ if (Array.isArray(value)) {
18
+ return value
19
+ .map((v) => (typeof v === 'string' ? v : v?.address || ''))
20
+ .filter(Boolean)
21
+ .join(', ');
22
+ }
23
+ if (typeof value === 'object' && value.address)
24
+ return value.address;
25
+ return '';
26
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared math utilities used across dashboard, collectors, and chart aggregator.
3
+ */
4
+ /** Round a number to 2 decimal places. */
5
+ export declare function round(n: number): number;
6
+ /** Clamp a value between min and max. */
7
+ export declare function clamp(value: number, min: number, max: number): number;
8
+ //# sourceMappingURL=math_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math_helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/math_helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,0CAA0C;AAC1C,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvC;AAED,yCAAyC;AACzC,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared math utilities used across dashboard, collectors, and chart aggregator.
3
+ */
4
+ /** Round a number to 2 decimal places. */
5
+ export function round(n) {
6
+ return Math.round(n * 100) / 100;
7
+ }
8
+ /** Clamp a value between min and max. */
9
+ export function clamp(value, min, max) {
10
+ return Math.max(min, Math.min(max, value));
11
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared time/range utilities for dashboard store, controller, and chart aggregator.
3
+ */
4
+ /** Convert a range string (e.g. '1h', '7d') to total minutes. */
5
+ export declare function rangeToMinutes(range: string): number;
6
+ /** Convert a range string to a SQLite-compatible datetime cutoff. */
7
+ export declare function rangeToCutoff(range: string): string;
8
+ /** Convert a Date to a SQLite-compatible datetime string (YYYY-MM-DD HH:MM:SS). */
9
+ export declare function toSqliteTimestamp(date: Date): string;
10
+ /** Round a bucket timestamp string down to the nearest N minutes. */
11
+ export declare function roundBucket(bucket: string, minutes: number): string;
12
+ //# sourceMappingURL=time_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time_helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/time_helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEpD;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnE"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Shared time/range utilities for dashboard store, controller, and chart aggregator.
3
+ */
4
+ const RANGE_MAP = {
5
+ '5m': 5,
6
+ '15m': 15,
7
+ '30m': 30,
8
+ '1h': 60,
9
+ '6h': 360,
10
+ '24h': 1440,
11
+ '7d': 10080,
12
+ };
13
+ /** Convert a range string (e.g. '1h', '7d') to total minutes. */
14
+ export function rangeToMinutes(range) {
15
+ return RANGE_MAP[range] ?? 60;
16
+ }
17
+ /** Convert a range string to a SQLite-compatible datetime cutoff. */
18
+ export function rangeToCutoff(range) {
19
+ const minutes = rangeToMinutes(range);
20
+ return toSqliteTimestamp(new Date(Date.now() - minutes * 60_000));
21
+ }
22
+ /** Convert a Date to a SQLite-compatible datetime string (YYYY-MM-DD HH:MM:SS). */
23
+ export function toSqliteTimestamp(date) {
24
+ return date.toISOString().replace('T', ' ').slice(0, 19);
25
+ }
26
+ /** Round a bucket timestamp string down to the nearest N minutes. */
27
+ export function roundBucket(bucket, minutes) {
28
+ const date = new Date(bucket.replace(' ', 'T') + 'Z');
29
+ const ms = minutes * 60_000;
30
+ const rounded = new Date(Math.floor(date.getTime() / ms) * ms);
31
+ return toSqliteTimestamp(rounded);
32
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Try to locate and read the @adonisjs/transmit-client build file.
3
+ * Returns the file contents wrapped to expose `window.Transmit`, or
4
+ * an empty string if the package is not installed.
5
+ *
6
+ * @param packageJsonPath - Absolute path to a package.json for require resolution
7
+ */
8
+ export declare function loadTransmitClient(packageJsonPath: string): string;
9
+ //# sourceMappingURL=transmit_client.d.ts.map