nestjs-profiler 1.0.25 → 1.0.27

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 (40) hide show
  1. package/README.md +254 -147
  2. package/collectors/event-collector.d.ts +18 -0
  3. package/collectors/event-collector.js +254 -0
  4. package/collectors/event-collector.js.map +1 -0
  5. package/common/profiler-options.interface.d.ts +8 -0
  6. package/common/profiler.model.d.ts +25 -0
  7. package/controllers/profiler.controller.d.ts +17 -1
  8. package/controllers/profiler.controller.js +129 -17
  9. package/controllers/profiler.controller.js.map +1 -1
  10. package/middleware/profiler-auth.middleware.d.ts +10 -0
  11. package/middleware/profiler-auth.middleware.js +110 -0
  12. package/middleware/profiler-auth.middleware.js.map +1 -0
  13. package/package.json +2 -2
  14. package/profiler.module.js +103 -1
  15. package/profiler.module.js.map +1 -1
  16. package/services/cron-explorer.service.d.ts +48 -0
  17. package/services/cron-explorer.service.js +260 -0
  18. package/services/cron-explorer.service.js.map +1 -0
  19. package/services/entity-explorer.service.d.ts +1 -1
  20. package/services/entity-explorer.service.js +7 -7
  21. package/services/entity-explorer.service.js.map +1 -1
  22. package/services/health.service.js +23 -8
  23. package/services/health.service.js.map +1 -1
  24. package/services/profiler.service.d.ts +10 -1
  25. package/services/profiler.service.js +103 -35
  26. package/services/profiler.service.js.map +1 -1
  27. package/services/route-explorer.service.d.ts +23 -1
  28. package/services/route-explorer.service.js +136 -10
  29. package/services/route-explorer.service.js.map +1 -1
  30. package/services/template-builder.service.d.ts +1 -0
  31. package/services/template-builder.service.js +184 -83
  32. package/services/template-builder.service.js.map +1 -1
  33. package/services/view.service.d.ts +1 -1
  34. package/services/view.service.js +32 -23
  35. package/services/view.service.js.map +1 -1
  36. package/views/cron-jobs.html +635 -0
  37. package/views/events.html +763 -0
  38. package/views/layout.html +40 -9
  39. package/views/login.html +277 -0
  40. package/views/routes.html +405 -37
package/README.md CHANGED
@@ -4,253 +4,360 @@
4
4
  <img src="https://raw.githubusercontent.com/MohammedRaslan/Nest-JS-Profiler/refs/heads/main/libs/nestjs-profiler/src/assets/logo.png" width="400" alt="NestJS Profiler Logo" />
5
5
  </p>
6
6
 
7
- A NestJS module for profiling HTTP requests, database queries, cache operations, outbound HTTP calls, application logs, package health, and code quality. Inspired by Symfony Profiler, it provides a web-based dashboard to inspect everything that happens inside a request — from DB queries to downstream API calls — in real time.
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/nestjs-profiler"><img src="https://img.shields.io/npm/v/nestjs-profiler.svg" alt="npm version" /></a>
9
+ <a href="https://www.npmjs.com/package/nestjs-profiler"><img src="https://img.shields.io/npm/dm/nestjs-profiler.svg" alt="npm downloads" /></a>
10
+ <img src="https://img.shields.io/badge/node-%3E%3D16-brightgreen" alt="node version" />
11
+ <img src="https://img.shields.io/badge/license-MIT-blue" alt="license" />
12
+ </p>
8
13
 
9
- ## Features
14
+ > A drop-in debugging dashboard for NestJS. Inspect HTTP requests, database queries, outbound calls, logs, events, scheduled jobs, and code health — all from one browser tab, with zero instrumentation required.
10
15
 
11
- - **HTTP Request Tracing** — Tracks method, URL, controller handler, duration, status code, headers, and request body.
12
- - **Database Profiling**
13
- - **PostgreSQL** — Captures all queries via `pg` (compatible with TypeORM, MikroORM, raw pg). Supports **Auto-Explain** to run `EXPLAIN` or `EXPLAIN ANALYZE` on slow queries automatically.
14
- - **MongoDB** — Profiles MongoDB commands and queries.
15
- - **MySQL** — Profiles MySQL queries.
16
- - **N+1 Detection** — Automatically flags repeated identical queries within the same request.
17
- - **Slow Query Tagging** — Tags queries exceeding 100ms.
18
- - **Sequential Scan Detection** — Tags queries using a Seq Scan from the explain plan.
19
- - **Outbound HTTP Tracking** — Captures every outbound `http`/`https` call made during a request: URL, method, status code, duration, and headers. Works automatically with axios, node-fetch, and any library built on Node's `http`/`https` modules. Enabled by default — no configuration required.
20
- - **Cache Profiling** — Tracks cache operations (get, set, del, reset) and hit/miss ratio when using `@nestjs/cache-manager`.
21
- - **Log Profiling** — Captures application logs associated with each request context.
22
- - **Live Logs Terminal** — Real-time streaming log viewer at `/__profiler/view/logs/live` via Server-Sent Events. Supports level filtering, search, pause/resume, and auto-scroll.
23
- - **Summary Dashboard** — Aggregate statistics: avg/p95 duration, error rate, cache hit rate, top slow endpoints, top slow queries, and recent errors.
24
- - **Entity Explorer** — Lists all registered TypeORM/MikroORM entities and their columns.
25
- - **Route Explorer** — Lists all registered routes with their controllers and handlers.
26
- - **Package Health** — Runs `npm audit` and `npm outdated` to surface known vulnerabilities and stale dependencies. Results are cached for 5 minutes. Works with npm, yarn, and pnpm. If the registry is unreachable, outdated packages are still shown with an inline warning.
27
- - **Code Quality** — Runs ESLint and TypeScript compiler checks (`tsc --noEmit`) against your source code. Issues are displayed grouped by file or by rule, with direct links to ESLint rule docs and TypeScript error references. Auto-fixable issues are flagged. File paths are copyable with one click.
28
- - **Web UI** — Built-in dashboard at `/__profiler` with no external dependencies.
29
- - **Zero Hard Dependencies** — Core functionality works out of the box; database drivers are optional peer dependencies.
16
+ ---
30
17
 
31
- ## Installation
18
+ > ⚠️ **Development use only.** The profiler adds request overhead and exposes internal application data. Always set `enabled: process.env.NODE_ENV !== 'production'`.
19
+
20
+ ---
21
+
22
+ ## Quick Start
23
+
24
+ **1. Install**
32
25
 
33
26
  ```bash
34
27
  npm install nestjs-profiler
35
28
  ```
36
29
 
37
- ### Peer Dependencies (Optional)
30
+ **2. Register in your AppModule**
31
+
32
+ ```typescript
33
+ import { ProfilerModule } from 'nestjs-profiler';
34
+
35
+ @Module({
36
+ imports: [
37
+ ProfilerModule.forRoot({
38
+ enabled: process.env.NODE_ENV !== 'production',
39
+ }),
40
+ ],
41
+ })
42
+ export class AppModule {}
43
+ ```
44
+
45
+ **3. Initialize in main.ts**
46
+
47
+ ```typescript
48
+ import { ProfilerModule } from 'nestjs-profiler';
49
+
50
+ async function bootstrap() {
51
+ const app = await NestFactory.create(AppModule);
52
+ ProfilerModule.initialize(app); // enables Route Explorer, Entity Explorer, Scheduled Jobs
53
+ await app.listen(3000);
54
+ }
55
+ ```
56
+
57
+ ---
58
+
59
+ ### Global Prefix (Required if you use global route prefix)
60
+
61
+ If your app uses a global route prefix, exclude the profiler:
62
+
63
+ ```typescript
64
+ app.setGlobalPrefix('api', {
65
+ exclude: [{ path: '__profiler/(.*)', method: RequestMethod.ALL }],
66
+ });
67
+ ```
68
+
69
+ Open `http://localhost:3000/__profiler` — the dashboard is live.
38
70
 
39
- Install only the dependencies relevant to your project:
71
+ ---
72
+
73
+ ## Features
74
+
75
+ ### Request Profiling
76
+ - Traces every HTTP request: method, URL, handler, status code, duration, headers, and body
77
+ - Summary dashboard with avg/p95 duration, error rate, cache hit rate, top slow endpoints, and recent errors
78
+ - Full detail view per request including all associated queries, cache ops, logs, and outbound calls
79
+
80
+ ### Database
81
+ - **PostgreSQL** — captures all queries via `pg`, compatible with TypeORM, MikroORM, and raw pg
82
+ - **MongoDB** — profiles all MongoDB commands
83
+ - **MySQL** — profiles MySQL queries via `mysql2`
84
+ - **N+1 Detection** — flags repeated identical queries within the same request
85
+ - **Slow Query Tagging** — highlights queries over 100ms
86
+ - **Sequential Scan Detection** — flags full table scans from the query explain plan
87
+ - **Auto-Explain** — automatically runs `EXPLAIN` or `EXPLAIN ANALYZE` on slow queries (opt-in)
88
+
89
+ ### Outbound HTTP
90
+ Automatically captures every `http`/`https` call your app makes — including axios, node-fetch, and any library built on Node's core modules. Records method, URL, status code, duration, headers (with Authorization and Cookie values redacted), and errors. No configuration required.
91
+
92
+ ### Cache
93
+ Tracks `get`, `set`, `del`, and `reset` operations with hit/miss ratio when using `@nestjs/cache-manager`.
94
+
95
+ ### Logs
96
+ - Captures application logs per request context
97
+ - **Live Logs Terminal** — real-time streaming viewer via Server-Sent Events, with level filtering, search, pause/resume, and auto-scroll
98
+
99
+ ### Code Analysis
100
+ - **Package Health** — runs `npm audit` and `npm outdated` to surface vulnerabilities and stale dependencies, sorted by severity
101
+ - **Code Quality** — runs ESLint and `tsc --noEmit` against your source. Issues shown by file or by rule, with links to rule docs and TypeScript error references. Auto-fixable issues are flagged
102
+
103
+ ### Application Intelligence
104
+ - **Route Explorer** — every registered route grouped by controller, with path/query/header params, body DTOs, property types, and source file paths
105
+ - **Entity Explorer** — all registered TypeORM/MikroORM entities with their columns
106
+ - **Event Tracking** — intercepts every `EventEmitter2` emission and renders a cascading tree: which service fired it, which listeners handled it, individual timings, child events, and errors. Requires `@nestjs/event-emitter`
107
+ - **Scheduled Jobs** — live view of all `@Cron`, `@Interval`, and `@Timeout` jobs from `@nestjs/schedule`, with countdowns, last run times, cycle progress, and handler details. Requires `@nestjs/schedule`
108
+
109
+ ### Security
110
+ - **Dashboard Authentication** — optional login wall with HMAC-SHA256 tokens stored in `localStorage`, 24-hour TTL. No separate auth server needed
111
+
112
+ ---
113
+
114
+ ## Installation
40
115
 
41
116
  ```bash
42
- # For PostgreSQL
43
- npm install pg
117
+ npm install nestjs-profiler
118
+ ```
44
119
 
45
- # For MongoDB
46
- npm install mongodb
120
+ ### Optional Peer Dependencies
47
121
 
48
- # For MySQL
49
- npm install mysql2
122
+ Install only what your project uses:
50
123
 
51
- # For Cache Profiling
52
- npm install @nestjs/cache-manager cache-manager
124
+ ```bash
125
+ npm install pg # PostgreSQL
126
+ npm install mongodb # MongoDB
127
+ npm install mysql2 # MySQL
128
+ npm install @nestjs/cache-manager cache-manager # Cache profiling
129
+ npm install @nestjs/event-emitter # Event tracking
130
+ npm install @nestjs/schedule # Scheduled jobs
53
131
  ```
54
132
 
133
+ ---
134
+
55
135
  ## Configuration
56
136
 
57
- Import `ProfilerModule` in your root `AppModule`:
137
+ All options are passed to `ProfilerModule.forRoot()`. Only `enabled` is required everything else is opt-in.
58
138
 
59
139
  ```typescript
60
- import { Module } from '@nestjs/common';
61
140
  import { ProfilerModule } from 'nestjs-profiler';
62
141
  import * as pg from 'pg';
63
142
 
64
143
  @Module({
65
144
  imports: [
66
145
  ProfilerModule.forRoot({
67
- // Global enable/disable (default: true)
68
- // Recommended: disable in production
69
146
  enabled: process.env.NODE_ENV !== 'production',
70
147
 
71
- // ── Database ─────────────────────────────────────────────────
72
- // PostgreSQL — pass the pg driver instance
148
+ // PostgreSQL
73
149
  pgDriver: pg,
74
150
  collectQueries: true,
75
-
76
- // Auto-Explain for slow queries
77
151
  explain: {
78
152
  enabled: true,
79
- thresholdMs: 50, // Only explain queries taking > 50ms
80
- analyze: false, // true = EXPLAIN ANALYZE (actually executes!)
153
+ thresholdMs: 100, // explain queries slower than this
154
+ analyze: false, // true = EXPLAIN ANALYZE (executes the query!)
81
155
  },
82
156
 
83
- // MongoDB — pass the mongodb driver instance
157
+ // MongoDB
84
158
  mongoDriver: require('mongodb'),
85
159
  collectMongo: true,
86
160
 
87
- // MySQL — pass the mysql2 driver instance
161
+ // MySQL
88
162
  mysqlDriver: require('mysql2'),
89
163
  collectMysql: true,
90
164
 
91
- // ── Outbound HTTP ─────────────────────────────────────────────
92
- // Tracks all outbound http/https calls made during each request.
93
- // Enabled by default — set false to disable.
165
+ // Outbound HTTP (on by default)
94
166
  collectHttp: true,
95
167
 
96
- // ── Cache ─────────────────────────────────────────────────────
97
- collectCache: true, // requires @nestjs/cache-manager
168
+ // Cache
169
+ collectCache: true,
98
170
 
99
- // ── Logs ──────────────────────────────────────────────────────
171
+ // Logs
100
172
  collectLogs: true,
101
173
 
102
- // ── Storage ───────────────────────────────────────────────────
103
- // Default: in-memory (last 100 requests).
104
- // Pass a custom object implementing ProfilerStorage for persistence.
105
- storage: 'memory',
174
+ // Auth (off by default)
175
+ auth: {
176
+ enabled: true,
177
+ username: 'admin',
178
+ password: 'supersecret',
179
+ },
106
180
  }),
107
181
  ],
108
182
  })
109
183
  export class AppModule {}
110
184
  ```
111
185
 
112
- ### Default behaviour
186
+ ### Options Reference
113
187
 
114
- | Option | Default | Notes |
188
+ | Option | Default | Description |
115
189
  |---|---|---|
116
- | `enabled` | `true` | Set `false` or tie to `NODE_ENV` |
117
- | `collectHttp` | `true` | Patches `http`/`https` automatically |
118
- | `collectLogs` | `true` | |
119
- | `collectQueries` | `true` | Requires `pgDriver` / `mongoDriver` / `mysqlDriver` |
120
- | `collectCache` | `true` | Requires `@nestjs/cache-manager` |
121
- | `explain.enabled` | `false` | Opt-in only |
122
-
123
- ## Usage
190
+ | `enabled` | `true` | Master switch. Tie to `NODE_ENV` in production |
191
+ | `collectHttp` | `true` | Outbound HTTP tracking (patches `http`/`https`) |
192
+ | `collectLogs` | `true` | Log capture per request |
193
+ | `collectQueries` | `true` | DB query capture. Requires a driver to be passed |
194
+ | `collectCache` | `true` | Cache op tracking. Requires `@nestjs/cache-manager` |
195
+ | `explain.enabled` | `false` | Auto-Explain for slow queries |
196
+ | `explain.thresholdMs` | `100` | Minimum query duration to trigger explain |
197
+ | `explain.analyze` | `false` | Run `EXPLAIN ANALYZE` instead of `EXPLAIN` |
198
+ | `auth.enabled` | `false` | Enable login wall. `username` and `password` required when `true` |
199
+ | Event Tracking | automatic | Activates when `@nestjs/event-emitter` is detected |
200
+ | Scheduled Jobs | automatic | Activates when `@nestjs/schedule` is detected |
124
201
 
125
- ### 1. Initialize Explorers (Optional but Recommended)
202
+ ---
126
203
 
127
- To enable the **Entity Explorer** and **Route Explorer**, call `initialize` in `main.ts` after creating the app:
204
+ ## Dashboard
128
205
 
129
- ```typescript
130
- import { NestFactory } from '@nestjs/core';
131
- import { AppModule } from './app.module';
132
- import { ProfilerModule } from 'nestjs-profiler';
206
+ Navigate to `/__profiler` after starting your app.
133
207
 
134
- async function bootstrap() {
135
- const app = await NestFactory.create(AppModule);
136
-
137
- ProfilerModule.initialize(app);
138
-
139
- await app.listen(3000);
140
- }
141
- bootstrap();
142
- ```
143
-
144
- ### 2. Accessing the Dashboard
145
-
146
- Once configured, start your application. The profiler automatically intercepts all requests.
147
-
148
- Navigate to `http://localhost:3000/__profiler`.
149
-
150
- #### Dashboard Pages
151
-
152
- | Path | Description |
208
+ | Page | Description |
153
209
  |---|---|
154
- | `/__profiler` | Redirects to Summary (default landing page) |
155
210
  | `/__profiler/view/summary` | Aggregate stats: avg/p95 duration, error rate, top slow endpoints |
156
- | `/__profiler/view/requests` | All captured requests |
157
- | `/__profiler/view/queries` | All database queries across requests, sorted by duration |
158
- | `/__profiler/view/http-calls` | All outbound HTTP calls across requests, sorted by duration |
211
+ | `/__profiler/view/requests` | All captured requests with status, duration, and method |
212
+ | `/__profiler/view/queries` | All DB queries across requests, sortable by duration |
213
+ | `/__profiler/view/http-calls` | All outbound HTTP calls, sortable by duration |
159
214
  | `/__profiler/view/logs` | Paginated application logs |
160
- | `/__profiler/view/logs/live` | Live streaming terminal — real-time log output |
215
+ | `/__profiler/view/logs/live` | Real-time streaming log terminal |
161
216
  | `/__profiler/view/cache` | Cache operations with hit/miss breakdown |
162
- | `/__profiler/view/entities` | Registered database entities |
163
- | `/__profiler/view/routes` | All registered application routes |
217
+ | `/__profiler/view/entities` | Registered database entities and their columns |
218
+ | `/__profiler/view/routes` | All registered routes with DTOs and parameter types |
164
219
  | `/__profiler/view/health` | Package vulnerabilities and outdated dependency report |
165
- | `/__profiler/view/code-quality` | ESLint and TypeScript static analysis report |
220
+ | `/__profiler/view/code-quality` | ESLint and TypeScript static analysis |
221
+ | `/__profiler/view/events` | Event cascade tree for `EventEmitter2` emissions |
222
+ | `/__profiler/view/cron-jobs` | Live scheduled job monitor — cron, intervals, and timeouts |
166
223
  | `/__profiler/:id` | Full detail view for a single request |
167
224
 
168
- ### 3. Outbound HTTP Tracking
225
+ ### JSON API
169
226
 
170
- Outbound HTTP tracking is **enabled by default**. Any `http.request`, `https.request`, `http.get`, or `https.get` call made during a request is automatically captured — including calls made via axios, node-fetch, and similar libraries.
227
+ All data is also available as JSON for programmatic use:
171
228
 
172
- Each captured call records:
229
+ ```
230
+ GET /__profiler/json # all captured requests
231
+ GET /__profiler/:id/json # single request detail
232
+ GET /__profiler/api/health # package health (5 min cache)
233
+ GET /__profiler/api/health?force=true
234
+ GET /__profiler/api/code-quality # static analysis (5 min cache)
235
+ GET /__profiler/api/code-quality?force=true
236
+ GET /__profiler/api/events # event log (live, not cached)
237
+ GET /__profiler/api/cron-jobs # scheduled job state (live, not cached)
238
+ ```
173
239
 
174
- - Method and full URL
175
- - HTTP vs HTTPS protocol
176
- - Response status code
177
- - Duration in ms
178
- - Request and response headers (Authorization/Cookie values are automatically redacted)
179
- - Error message if the call failed
240
+ ---
180
241
 
181
- You can view outbound calls for a specific request in the request detail view, or browse all calls across all requests at `/__profiler/view/http-calls`.
242
+ ## Feature Guides
182
243
 
183
- To disable:
244
+ ### Dashboard Authentication
184
245
 
185
246
  ```typescript
186
- ProfilerModule.forRoot({ collectHttp: false })
247
+ ProfilerModule.forRoot({
248
+ auth: {
249
+ enabled: true,
250
+ username: 'admin',
251
+ password: 'supersecret',
252
+ },
253
+ })
187
254
  ```
188
255
 
189
- ### 4. Package Health
256
+ When enabled, all `/__profiler` pages check for a valid token in `localStorage` before rendering. If none is found, the browser redirects to the login page. Tokens use HMAC-SHA256 keyed on the password and expire after 24 hours — changing the password invalidates all active sessions automatically.
190
257
 
191
- The Health tab runs `npm audit` and `npm outdated` from your project root and displays the results in a searchable UI.
258
+ TypeScript enforces that `username` and `password` are present when `enabled: true`. Omitting either is a compile-time error.
192
259
 
193
- - **Vulnerabilities** sorted by severity (critical high moderate low), with fix availability and whether the package is a direct or transitive dependency.
194
- - **Outdated packages** — shows current, wanted, and latest versions with major-update warnings.
195
- - Results are **cached for 5 minutes** server-side. Navigating back to the tab shows the cached result instantly without re-running. Click **Re-run audit** to force a fresh scan.
196
- - If `npm audit` cannot reach the registry (e.g. VPN or proxy), the outdated packages section still renders with an inline warning for the unavailable audit.
197
- - No configuration required — works automatically for npm, yarn, and pnpm projects.
260
+ > Auth is enforced client-side. It prevents casual access on shared dev/staging environments but is not a security boundary for sensitive data.
198
261
 
199
- #### JSON endpoint
262
+ | Route | Purpose |
263
+ |---|---|
264
+ | `GET /__profiler/login` | Login page |
265
+ | `POST /__profiler/api/login` | Validates credentials, returns a session token |
266
+ | `GET /__profiler/logout` | Clears the token and redirects to login |
200
267
 
201
- ```
202
- GET /__profiler/api/health # cached result (5 min TTL)
203
- GET /__profiler/api/health?force=true # force fresh scan
204
- ```
268
+ ---
205
269
 
206
- ### 5. Code Quality
270
+ ### Event Tracking
207
271
 
208
- The Code Quality tab runs static analysis tools against your source code and surfaces every issue without AI or external services.
272
+ Requires `@nestjs/event-emitter`:
209
273
 
210
- **ESLint** — uses your project's existing ESLint configuration (`node_modules/.bin/eslint`). Results are shown in two views:
274
+ ```typescript
275
+ import { EventEmitterModule } from '@nestjs/event-emitter';
211
276
 
212
- - **By File** — expandable accordion rows per file. Each issue shows line:column, severity badge, message, fix indicator (⚡ auto-fixable), and a clickable rule badge linking to the ESLint documentation.
213
- - **By Rule** — sorted by severity then count, showing how many files are affected per rule.
277
+ @Module({
278
+ imports: [EventEmitterModule.forRoot()],
279
+ })
280
+ export class AppModule {}
281
+ ```
214
282
 
215
- **TypeScript** runs `tsc --noEmit` using your project's `tsconfig.json`. Each error links to `typescript.tv/errors` for explanations.
283
+ The profiler intercepts every `emit` and `emitAsync` call automatically. No decorators or instrumentation needed. The dashboard renders a full cascade tree showing the emitter, all listeners with timings, child events, and any listener errors.
216
284
 
217
- **Summary cards** show total issues, errors, warnings, auto-fixable count, and files affected at a glance.
285
+ **Example what you see in the dashboard:**
218
286
 
219
- File paths have a **copy-to-clipboard** button that appears on hover, making it easy to jump to the file in your editor.
287
+ ```
288
+ 🔔 order.created (async) ⬆ OrderService.createOrder 145ms
289
+ ✓ onOrderCreated [InventoryListener] 45ms
290
+ ✓ onOrderCreated [InvoiceListener] 80ms
291
+ ✓ onOrderCreated [AuditListener] 5ms
292
+ └── 🔔 inventory.reserved ⬆ InventoryListener 23ms
293
+ ✓ onInventoryReserved [NotificationListener] 20ms
294
+ └── 🔔 invoice.created ⬆ InvoiceListener 4ms
295
+ ✓ onInvoiceCreated [AuditListener] 3ms
296
+ ```
220
297
 
221
- Results are cached for 5 minutes. Click **Re-run** to force a fresh analysis.
298
+ ---
222
299
 
223
- > **Note:** Code Quality only lints the `src/` directory (or project root if `src/` doesn't exist) and automatically ignores `dist/`, `build/`, `coverage/`, and other generated directories.
300
+ ### Scheduled Jobs
224
301
 
225
- #### JSON endpoint
302
+ Requires `@nestjs/schedule`:
226
303
 
304
+ ```bash
305
+ npm install @nestjs/schedule
227
306
  ```
228
- GET /__profiler/api/code-quality # cached result (5 min TTL)
229
- GET /__profiler/api/code-quality?force=true # force fresh scan
307
+
308
+ ```typescript
309
+ import { ScheduleModule } from '@nestjs/schedule';
310
+
311
+ @Module({
312
+ imports: [ScheduleModule.forRoot()],
313
+ })
314
+ export class AppModule {}
230
315
  ```
231
316
 
232
- ### 6. JSON API
317
+ The profiler detects `SchedulerRegistry` at startup via `ProfilerModule.initialize(app)` no additional configuration needed. The dashboard has three tabs:
233
318
 
234
- Retrieve profile data programmatically:
319
+ **Cron Jobs** one card per `@Cron()` method showing the expression with a plain-English translation (e.g. `0 */5 * * * *` → *Every 5 minutes*), a live next-run countdown, last run time, cycle progress bar, handler name, and source file path. An *Upcoming — next 3 hours* strip at the top plots all jobs on a shared timeline.
235
320
 
236
- - `GET /__profiler/json` List all captured requests
237
- - `GET /__profiler/:id/json` — Details for a specific request
321
+ **Intervals** one card per `@Interval()` method with an animated frequency ring, the repeat period displayed prominently (e.g. *Every 30s*), and fires-per-minute count.
238
322
 
239
- ## Global Prefix
323
+ **Timeouts** one card per `@Timeout()` method. Pending jobs show a live countdown in amber; fired jobs turn grey with a *Fired* badge. Both show the configured delay and the handler that will run.
240
324
 
241
- If your app uses a global prefix (e.g. `/api`), exclude the profiler routes:
325
+ All tabs auto-refresh every 15 seconds. If `@nestjs/schedule` is not installed, the page shows an install prompt instead of an error.
326
+
327
+ **Example:**
242
328
 
243
329
  ```typescript
244
- app.setGlobalPrefix('api', {
245
- exclude: [{ path: '__profiler/(.*)', method: RequestMethod.ALL }],
246
- });
330
+ import { Cron, CronExpression, Interval, Timeout } from '@nestjs/schedule';
331
+
332
+ @Injectable()
333
+ export class TasksService {
334
+
335
+ @Cron(CronExpression.EVERY_MINUTE, { name: 'health-ping' })
336
+ handleHealthPing() { /* ... */ }
337
+
338
+ @Cron('0 0 * * *', { name: 'nightly-cleanup' })
339
+ handleNightlyCleanup() { /* ... */ }
340
+
341
+ @Interval('metrics-flush', 30_000)
342
+ handleMetricsFlush() { /* ... */ }
343
+
344
+ @Timeout('deferred-init', 10_000)
345
+ handleDeferredInit() { /* ... */ }
346
+ }
247
347
  ```
248
348
 
249
- ## Important Notes
349
+ ---
350
+
351
+ ### Route Explorer
352
+
353
+ Populated by `ProfilerModule.initialize(app)`. Lists every route grouped by controller in an expandable accordion. Each route surfaces:
354
+
355
+ - HTTP method and full path (including global prefix)
356
+ - Path parameters, query parameters, and headers with their TypeScript types
357
+ - Body DTO — class name, all decorated properties and types (discovered via `reflect-metadata`)
358
+ - Source file path with a one-click copy button
250
359
 
251
- - The profiler is designed for **development and debugging only**. Do not enable in production it adds request overhead and exposes internal application data.
252
- - The default in-memory storage holds the last 100 requests. Older profiles are evicted automatically.
253
- - Outbound HTTP tracking patches `http`/`https` at the Node.js module level. The patch is applied once on module init and is safe for hot-reload (double-patch is guarded).
360
+ Works with `emitDecoratorMetadata: true` (standard in NestJS). No OpenAPI/Swagger required.
254
361
 
255
362
  ## License
256
363
 
@@ -0,0 +1,18 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { ProfilerService } from '../services/profiler.service';
3
+ export declare class EventCollector implements OnModuleInit {
4
+ private readonly profilerService;
5
+ private readonly eventEmitter?;
6
+ private resolvedListenerNames;
7
+ private readonly listenerRegistrationCounters;
8
+ constructor(profilerService: ProfilerService, eventEmitter?: any | undefined);
9
+ setListenerNames(map: Map<string, Array<{
10
+ name: string;
11
+ file: string;
12
+ }>>): void;
13
+ onModuleInit(): void;
14
+ private patchEmitter;
15
+ private buildProfile;
16
+ private serializePayload;
17
+ private getCallerLocation;
18
+ }