adonisjs-server-stats 1.3.2 → 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 +258 -489
  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 +39 -3
  15. package/dist/src/dashboard/dashboard_store.d.ts.map +1 -1
  16. package/dist/src/dashboard/dashboard_store.js +145 -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 +555 -165
  49. package/dist/src/edge/client/dashboard.js +2797 -1556
  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,10 +1,10 @@
1
- import { writeFile, readFile, rename, mkdir } from "node:fs/promises";
2
- import { dirname } from "node:path";
3
- import { QueryCollector } from "./query_collector.js";
4
- import { EventCollector } from "./event_collector.js";
5
- import { EmailCollector } from "./email_collector.js";
6
- import { RouteInspector } from "./route_inspector.js";
7
- import { TraceCollector } from "./trace_collector.js";
1
+ import { writeFile, readFile, rename, mkdir } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ import { EmailCollector } from './email_collector.js';
4
+ import { EventCollector } from './event_collector.js';
5
+ import { QueryCollector } from './query_collector.js';
6
+ import { RouteInspector } from './route_inspector.js';
7
+ import { TraceCollector } from './trace_collector.js';
8
8
  /**
9
9
  * Singleton store holding all debug data collectors.
10
10
  * Bound to the AdonisJS container as `debug.store`.
@@ -56,16 +56,16 @@ export class DebugStore {
56
56
  data.traces = this.traces.getTraces();
57
57
  }
58
58
  const json = JSON.stringify(data);
59
- const tmpPath = filePath + ".tmp";
59
+ const tmpPath = filePath + '.tmp';
60
60
  await mkdir(dirname(filePath), { recursive: true });
61
- await writeFile(tmpPath, json, "utf-8");
61
+ await writeFile(tmpPath, json, 'utf-8');
62
62
  await rename(tmpPath, filePath);
63
63
  }
64
64
  /** Restore collector data from a JSON file on disk. */
65
65
  async loadFromDisk(filePath) {
66
66
  let raw;
67
67
  try {
68
- raw = await readFile(filePath, "utf-8");
68
+ raw = await readFile(filePath, 'utf-8');
69
69
  }
70
70
  catch {
71
71
  return; // file doesn't exist yet
@@ -21,18 +21,9 @@ export declare class EmailCollector {
21
21
  getTotalCount(): number;
22
22
  clear(): void;
23
23
  private buildRecord;
24
- /**
25
- * Normalize various address formats to a comma-separated string.
26
- *
27
- * AdonisJS mail addresses can be:
28
- * - A string: `"user@example.com"`
29
- * - An object: `{ address: "user@example.com", name: "User" }`
30
- * - An array of strings or objects
31
- */
32
24
  /** Register a callback that fires whenever a new email is recorded. */
33
25
  onNewItem(cb: ((item: EmailRecord) => void) | null): void;
34
26
  /** Restore persisted records into the buffer and reset the ID counter. */
35
27
  loadRecords(records: EmailRecord[]): void;
36
- private extractAddresses;
37
28
  }
38
29
  //# sourceMappingURL=email_collector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"email_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/email_collector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAmD;gBAEvD,SAAS,GAAE,MAAY;IAI7B,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDxC,IAAI,IAAI,IAAI;IAUZ,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMvC,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,WAAW;IAsBnB;;;;;;;OAOG;IACH,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;IAMzC,OAAO,CAAC,gBAAgB;CAYzB"}
1
+ {"version":3,"file":"email_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/email_collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAmD;gBAEvD,SAAS,GAAE,MAAY;IAI7B,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDxC,IAAI,IAAI,IAAI;IAUZ,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMvC,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,WAAW;IAkBnB,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
@@ -1,3 +1,4 @@
1
+ import { extractAddresses } from '../utils/mail_helpers.js';
1
2
  import { RingBuffer } from './ring_buffer.js';
2
3
  /**
3
4
  * Listens to AdonisJS mail events and stores captured emails in a ring buffer.
@@ -26,7 +27,7 @@ export class EmailCollector {
26
27
  };
27
28
  const onSent = (data) => {
28
29
  const msg = data?.message || data;
29
- const to = this.extractAddresses(msg?.to);
30
+ const to = extractAddresses(msg?.to);
30
31
  const subject = msg?.subject || '';
31
32
  // Try to find the matching 'sending' record and update it
32
33
  const all = this.buffer.toArray();
@@ -92,10 +93,10 @@ export class EmailCollector {
92
93
  buildRecord(msg, status, data) {
93
94
  return {
94
95
  id: this.buffer.getNextId(),
95
- from: this.extractAddresses(msg?.from) || 'unknown',
96
- to: this.extractAddresses(msg?.to) || 'unknown',
97
- cc: this.extractAddresses(msg?.cc) || null,
98
- bcc: this.extractAddresses(msg?.bcc) || null,
96
+ from: extractAddresses(msg?.from) || 'unknown',
97
+ to: extractAddresses(msg?.to) || 'unknown',
98
+ cc: extractAddresses(msg?.cc) || null,
99
+ bcc: extractAddresses(msg?.bcc) || null,
99
100
  subject: msg?.subject || '(no subject)',
100
101
  html: msg?.html || null,
101
102
  text: msg?.text || null,
@@ -106,14 +107,6 @@ export class EmailCollector {
106
107
  timestamp: Date.now(),
107
108
  };
108
109
  }
109
- /**
110
- * Normalize various address formats to a comma-separated string.
111
- *
112
- * AdonisJS mail addresses can be:
113
- * - A string: `"user@example.com"`
114
- * - An object: `{ address: "user@example.com", name: "User" }`
115
- * - An array of strings or objects
116
- */
117
110
  /** Register a callback that fires whenever a new email is recorded. */
118
111
  onNewItem(cb) {
119
112
  this.buffer.onPush(cb);
@@ -124,19 +117,4 @@ export class EmailCollector {
124
117
  const maxId = records.reduce((m, r) => Math.max(m, r.id), 0);
125
118
  this.buffer.setNextId(maxId + 1);
126
119
  }
127
- extractAddresses(value) {
128
- if (!value)
129
- return '';
130
- if (typeof value === 'string')
131
- return value;
132
- if (Array.isArray(value)) {
133
- return value
134
- .map((v) => (typeof v === 'string' ? v : v?.address || ''))
135
- .filter(Boolean)
136
- .join(', ');
137
- }
138
- if (typeof value === 'object' && value.address)
139
- return value.address;
140
- return '';
141
- }
142
120
  }
@@ -1,4 +1,4 @@
1
- import type { EventRecord } from "./types.js";
1
+ import type { EventRecord } from './types.js';
2
2
  /**
3
3
  * Wraps the AdonisJS emitter to log all events with timestamps.
4
4
  * Uses monkey-patching of emitter.emit to intercept all events.
@@ -1 +1 @@
1
- {"version":3,"file":"event_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/event_collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,OAAO,CAAa;gBAEhB,SAAS,GAAE,MAAY;IAInC,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAmCzB,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,YAAY;IAapB,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
1
+ {"version":3,"file":"event_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/event_collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,OAAO,CAAY;gBAEf,SAAS,GAAE,MAAY;IAInC,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAmCzB,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,YAAY;IAapB,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
@@ -1,5 +1,5 @@
1
- import { RingBuffer } from "./ring_buffer.js";
2
- import { isExcludedRequest } from "../middleware/request_tracking_middleware.js";
1
+ import { isExcludedRequest } from '../middleware/request_tracking_middleware.js';
2
+ import { RingBuffer } from './ring_buffer.js';
3
3
  /**
4
4
  * Wraps the AdonisJS emitter to log all events with timestamps.
5
5
  * Uses monkey-patching of emitter.emit to intercept all events.
@@ -12,22 +12,22 @@ export class EventCollector {
12
12
  this.buffer = new RingBuffer(maxEvents);
13
13
  }
14
14
  start(emitter) {
15
- if (!emitter || typeof emitter.emit !== "function")
15
+ if (!emitter || typeof emitter.emit !== 'function')
16
16
  return;
17
17
  this.emitter = emitter;
18
18
  this.originalEmit = emitter.emit.bind(emitter);
19
19
  const self = this;
20
20
  emitter.emit = function (event, data) {
21
21
  // Resolve event name: class-based events use the class name, string events are used as-is
22
- const eventName = typeof event === "string" ? event : event?.name || "unknown";
22
+ const eventName = typeof event === 'string' ? event : event?.name || 'unknown';
23
23
  // Skip internal/noisy events, mail events (handled by EmailCollector),
24
24
  // HTTP lifecycle events (redundant with timeline), and events triggered
25
25
  // by debug panel polling requests
26
- if (!eventName.startsWith("__") &&
27
- eventName !== "db:query" &&
28
- !eventName.startsWith("mail:") &&
29
- eventName !== "queued:mail:error" &&
30
- eventName !== "http:request_completed" &&
26
+ if (!eventName.startsWith('__') &&
27
+ eventName !== 'db:query' &&
28
+ !eventName.startsWith('mail:') &&
29
+ eventName !== 'queued:mail:error' &&
30
+ eventName !== 'http:request_completed' &&
31
31
  !isExcludedRequest()) {
32
32
  const record = {
33
33
  id: self.buffer.getNextId(),
@@ -51,14 +51,14 @@ export class EventCollector {
51
51
  if (data === undefined || data === null)
52
52
  return null;
53
53
  try {
54
- if (typeof data === "string")
54
+ if (typeof data === 'string')
55
55
  return data;
56
56
  const json = JSON.stringify(data, this.safeReplacer(), 2);
57
57
  // Cap at 4KB per event to avoid memory bloat
58
- return json.length > 4096 ? json.slice(0, 4096) + "\n..." : json;
58
+ return json.length > 4096 ? json.slice(0, 4096) + '\n...' : json;
59
59
  }
60
60
  catch {
61
- if (typeof data === "object" && data.constructor?.name) {
61
+ if (typeof data === 'object' && data.constructor?.name) {
62
62
  return `[${data.constructor.name}]`;
63
63
  }
64
64
  return typeof data;
@@ -67,14 +67,14 @@ export class EventCollector {
67
67
  safeReplacer() {
68
68
  const seen = new WeakSet();
69
69
  return (_key, value) => {
70
- if (typeof value === "object" && value !== null) {
70
+ if (typeof value === 'object' && value !== null) {
71
71
  if (seen.has(value))
72
- return "[Circular]";
72
+ return '[Circular]';
73
73
  seen.add(value);
74
74
  }
75
- if (typeof value === "function")
76
- return `[Function: ${value.name || "anonymous"}]`;
77
- if (typeof value === "bigint")
75
+ if (typeof value === 'function')
76
+ return `[Function: ${value.name || 'anonymous'}]`;
77
+ if (typeof value === 'bigint')
78
78
  return value.toString();
79
79
  return value;
80
80
  };
@@ -1,4 +1,4 @@
1
- import type { QueryRecord } from "./types.js";
1
+ import type { QueryRecord } from './types.js';
2
2
  /**
3
3
  * Listens to Lucid's `db:query` event and stores queries in a ring buffer.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"query_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/query_collector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,OAAO,CAAsC;gBAEzC,UAAU,GAAE,MAAY,EAAE,eAAe,GAAE,MAAY;IAK7D,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCxC,IAAI,IAAI,IAAI;IAYZ,UAAU,IAAI,WAAW,EAAE;IAI3B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,UAAU;;;;;;IA0BV,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
1
+ {"version":3,"file":"query_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/query_collector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,OAAO,CAAqC;gBAExC,UAAU,GAAE,MAAY,EAAE,eAAe,GAAE,MAAY;IAK7D,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCxC,IAAI,IAAI,IAAI;IAQZ,UAAU,IAAI,WAAW,EAAE;IAI3B,SAAS,CAAC,CAAC,GAAE,MAAY,GAAG,WAAW,EAAE;IAIzC,UAAU;;;;;;IAqBV,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
@@ -1,5 +1,6 @@
1
- import { RingBuffer } from "./ring_buffer.js";
2
- import { isExcludedRequest } from "../middleware/request_tracking_middleware.js";
1
+ import { isExcludedRequest } from '../middleware/request_tracking_middleware.js';
2
+ import { round } from '../utils/math_helpers.js';
3
+ import { RingBuffer } from './ring_buffer.js';
3
4
  /**
4
5
  * Listens to Lucid's `db:query` event and stores queries in a ring buffer.
5
6
  *
@@ -24,33 +25,31 @@ export class QueryCollector {
24
25
  // Self-exclude: skip queries triggered by debug panel polling requests
25
26
  if (isExcludedRequest())
26
27
  return;
27
- const duration = typeof data.duration === "number"
28
+ const duration = typeof data.duration === 'number'
28
29
  ? data.duration
29
30
  : Array.isArray(data.duration)
30
31
  ? data.duration[0] * 1e3 + data.duration[1] / 1e6
31
32
  : 0;
32
33
  const record = {
33
34
  id: this.buffer.getNextId(),
34
- sql: data.sql || "",
35
+ sql: data.sql || '',
35
36
  bindings: data.bindings || [],
36
- duration: Math.round(duration * 100) / 100,
37
- method: data.method || "unknown",
37
+ duration: round(duration),
38
+ method: data.method || 'unknown',
38
39
  model: data.model || null,
39
- connection: data.connection || "default",
40
+ connection: data.connection || 'default',
40
41
  inTransaction: data.inTransaction || false,
41
42
  timestamp: Date.now(),
42
43
  };
43
44
  this.buffer.push(record);
44
45
  };
45
- if (emitter && typeof emitter.on === "function") {
46
- emitter.on("db:query", this.handler);
46
+ if (emitter && typeof emitter.on === 'function') {
47
+ emitter.on('db:query', this.handler);
47
48
  }
48
49
  }
49
50
  stop() {
50
- if (this.emitter &&
51
- this.handler &&
52
- typeof this.emitter.off === "function") {
53
- this.emitter.off("db:query", this.handler);
51
+ if (this.emitter && this.handler && typeof this.emitter.off === 'function') {
52
+ this.emitter.off('db:query', this.handler);
54
53
  }
55
54
  this.handler = null;
56
55
  this.emitter = null;
@@ -75,7 +74,7 @@ export class QueryCollector {
75
74
  total,
76
75
  slow,
77
76
  duplicates,
78
- avgDuration: Math.round(avgDuration * 100) / 100,
77
+ avgDuration: round(avgDuration),
79
78
  };
80
79
  }
81
80
  getTotalCount() {
@@ -1 +1 @@
1
- {"version":3,"file":"ring_buffer.d.ts","sourceRoot":"","sources":["../../../src/debug/ring_buffer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAU,CAAC,CAAC;IAOX,OAAO,CAAC,QAAQ;IAN5B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAoC;gBAEpC,QAAQ,EAAE,MAAM;IAIpC,oEAAoE;IACpE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAI5C,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IASnB,2DAA2D;IAC3D,OAAO,IAAI,CAAC,EAAE;IAcd,sDAAsD;IACtD,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE;IAKtB,SAAS,IAAI,MAAM;IAInB,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,IAAI;IAMb,mFAAmF;IACnF,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAMtB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAG5B"}
1
+ {"version":3,"file":"ring_buffer.d.ts","sourceRoot":"","sources":["../../../src/debug/ring_buffer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAU,CAAC,CAAC;IAOX,OAAO,CAAC,QAAQ;IAN5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,IAAI,CAAY;IACxB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAmC;gBAEnC,QAAQ,EAAE,MAAM;IAIpC,oEAAoE;IACpE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAI5C,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IASnB,2DAA2D;IAC3D,OAAO,IAAI,CAAC,EAAE;IAcd,sDAAsD;IACtD,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE;IAKtB,SAAS,IAAI,MAAM;IAInB,IAAI,IAAI,MAAM;IAId,KAAK,IAAI,IAAI;IAMb,mFAAmF;IACnF,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAMtB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAG5B"}
@@ -1,4 +1,4 @@
1
- import type { RouteRecord } from "./types.js";
1
+ import type { RouteRecord } from './types.js';
2
2
  /**
3
3
  * Reads the router's route table at boot time and caches it.
4
4
  * Static data computed once — routes don't change after boot.
@@ -1 +1 @@
1
- {"version":3,"file":"route_inspector.d.ts","sourceRoot":"","sources":["../../../src/debug/route_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAqB;IAEnC;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAoC1B,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,iBAAiB;IA2BzB,SAAS,IAAI,WAAW,EAAE;IAI1B,aAAa,IAAI,MAAM;CAGxB"}
1
+ {"version":3,"file":"route_inspector.d.ts","sourceRoot":"","sources":["../../../src/debug/route_inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAoB;IAElC;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAoC1B,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,iBAAiB;IA2BzB,SAAS,IAAI,WAAW,EAAE;IAI1B,aAAa,IAAI,MAAM;CAGxB"}
@@ -20,14 +20,14 @@ export class RouteInspector {
20
20
  continue;
21
21
  for (const route of domainRoutes) {
22
22
  const methods = Array.isArray(route.methods)
23
- ? route.methods.filter((m) => m !== "HEAD")
23
+ ? route.methods.filter((m) => m !== 'HEAD')
24
24
  : [];
25
25
  const handler = this.resolveHandler(route.handler);
26
26
  const middlewareList = this.resolveMiddleware(route.middleware);
27
27
  for (const method of methods) {
28
28
  this.routes.push({
29
29
  method,
30
- pattern: route.pattern || "/",
30
+ pattern: route.pattern || '/',
31
31
  name: route.name || null,
32
32
  handler,
33
33
  middleware: middlewareList,
@@ -42,15 +42,15 @@ export class RouteInspector {
42
42
  }
43
43
  resolveHandler(handler) {
44
44
  if (!handler)
45
- return "unknown";
46
- if (typeof handler === "string")
45
+ return 'unknown';
46
+ if (typeof handler === 'string')
47
47
  return handler;
48
- if (typeof handler === "function")
49
- return handler.name || "closure";
48
+ if (typeof handler === 'function')
49
+ return handler.name || 'closure';
50
50
  // Lazy import handler
51
51
  if (handler.reference) {
52
52
  const ref = handler.reference;
53
- if (typeof ref === "string")
53
+ if (typeof ref === 'string')
54
54
  return ref;
55
55
  if (Array.isArray(ref) && ref.length >= 2) {
56
56
  return `${ref[0]}#${ref[1]}`;
@@ -59,29 +59,29 @@ export class RouteInspector {
59
59
  // Handle object with name
60
60
  if (handler.name)
61
61
  return handler.name;
62
- return "unknown";
62
+ return 'unknown';
63
63
  }
64
64
  resolveMiddleware(middleware) {
65
65
  if (!middleware)
66
66
  return [];
67
67
  // AdonisJS v6 middleware is a Middleware instance from @poppinss/middleware.
68
68
  // Call .all() to get the Set of middleware items.
69
- const items = typeof middleware.all === "function"
69
+ const items = typeof middleware.all === 'function'
70
70
  ? middleware.all()
71
71
  : Array.isArray(middleware)
72
72
  ? middleware
73
73
  : [];
74
74
  const result = [];
75
75
  for (const m of items) {
76
- if (typeof m === "string") {
76
+ if (typeof m === 'string') {
77
77
  result.push(m);
78
78
  }
79
- else if (typeof m === "function") {
79
+ else if (typeof m === 'function') {
80
80
  if (m.name)
81
81
  result.push(m.name);
82
82
  }
83
83
  else if (m?.name) {
84
- const args = m.args?.length ? `(${JSON.stringify(m.args).slice(1, -1)})` : "";
84
+ const args = m.args?.length ? `(${JSON.stringify(m.args).slice(1, -1)})` : '';
85
85
  result.push(m.name + args);
86
86
  }
87
87
  // Skip unnamed global middleware (router.use lazy imports) — same for every route
@@ -1 +1 @@
1
- {"version":3,"file":"trace_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/trace_collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAmBxD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAG9E;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,GAAG,CAAwC;IACnD,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,mBAAmB,CAAmC;gBAElD,SAAS,GAAE,MAAY;IAKnC,qDAAqD;IACrD,UAAU,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,0GAA0G;IAC1G,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAsBhF,mDAAmD;IACnD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,IAAI;IAeP,+DAA+D;IACzD,IAAI,CAAC,CAAC,EACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC;IAyBb,uEAAuE;IACvE,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAsCzB,uDAAuD;IACvD,IAAI,IAAI,IAAI;IAaZ,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAInC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI7C,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
1
+ {"version":3,"file":"trace_collector.d.ts","sourceRoot":"","sources":["../../../src/debug/trace_collector.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAmBxD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAG9E;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,GAAG,CAAwC;IACnD,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,mBAAmB,CAAmC;gBAElD,SAAS,GAAE,MAAY;IAKnC,qDAAqD;IACrD,UAAU,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,0GAA0G;IAC1G,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAsBhF,mDAAmD;IACnD,OAAO,CACL,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,EAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC7B,IAAI;IAeP,+DAA+D;IACzD,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAyB/F,uEAAuE;IACvE,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAsCzB,uDAAuD;IACvD,IAAI,IAAI,IAAI;IAaZ,SAAS,IAAI,WAAW,EAAE;IAI1B,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAInC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI7C,aAAa,IAAI,MAAM;IAIvB,KAAK,IAAI,IAAI;IAIb,uEAAuE;IACvE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAIzD,0EAA0E;IAC1E,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI;CAK1C"}
@@ -1,5 +1,6 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks';
2
2
  import { performance } from 'node:perf_hooks';
3
+ import { round } from '../utils/math_helpers.js';
3
4
  import { RingBuffer } from './ring_buffer.js';
4
5
  /**
5
6
  * Module-level singleton reference for the `trace()` helper.
@@ -63,7 +64,7 @@ export class TraceCollector {
63
64
  method,
64
65
  url,
65
66
  statusCode,
66
- totalDuration: Math.round(totalDuration * 100) / 100,
67
+ totalDuration: round(totalDuration),
67
68
  spanCount: ctx.spans.length,
68
69
  spans: ctx.spans,
69
70
  warnings: ctx.warnings,
@@ -82,8 +83,8 @@ export class TraceCollector {
82
83
  parentId: ctx.currentSpanId,
83
84
  label,
84
85
  category,
85
- startOffset: Math.round(startOffset * 100) / 100,
86
- duration: Math.round(duration * 100) / 100,
86
+ startOffset: round(startOffset),
87
+ duration: round(duration),
87
88
  metadata,
88
89
  });
89
90
  }
@@ -106,8 +107,8 @@ export class TraceCollector {
106
107
  parentId,
107
108
  label,
108
109
  category,
109
- startOffset: Math.round((start - ctx.requestStart) * 100) / 100,
110
- duration: Math.round(duration * 100) / 100,
110
+ startOffset: round(start - ctx.requestStart),
111
+ duration: round(duration),
111
112
  });
112
113
  ctx.currentSpanId = parentId;
113
114
  }