@angelitosystems/nest-devtools 0.1.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # @angelitosystems/nest-devtools
2
+
3
+ > Debugging y observabilidad en tiempo real para aplicaciones NestJS.
4
+
5
+ Anade instrumentacion para peticiones HTTP, logs, errores, rendimiento, grafo de la aplicacion y, de forma opcional, WebSockets y base de datos. El SDK no debe detener ni romper la aplicacion si el servidor DevTools no esta disponible.
6
+
7
+ ## Requisitos
8
+
9
+ - Node.js 18 o superior, o Bun 1.1 o superior.
10
+ - NestJS 9, 10, 11 o 12.
11
+ - `reflect-metadata` y `rxjs`, normalmente ya presentes en una aplicacion NestJS.
12
+
13
+ ## Instalacion
14
+
15
+ ```bash
16
+ npm install @angelitosystems/nest-devtools
17
+ ```
18
+
19
+ ```bash
20
+ bun add @angelitosystems/nest-devtools
21
+ ```
22
+
23
+ El servidor y el dashboard se instalan aparte con [`@angelitosystems/nest-devtools-cli`](../cli).
24
+
25
+ ## Uso
26
+
27
+ Anade una linea despues de crear la aplicacion y antes de `listen()`:
28
+
29
+ ```ts
30
+ import { NestFactory } from '@nestjs/core';
31
+ import { AppModule } from './app.module';
32
+ import { NestDevTools } from '@angelitosystems/nest-devtools';
33
+
34
+ async function bootstrap() {
35
+ const app = await NestFactory.create(AppModule);
36
+ NestDevTools.init(app);
37
+ await app.listen(3000);
38
+ }
39
+
40
+ bootstrap();
41
+ ```
42
+
43
+ Despues inicia el CLI y abre `http://localhost:4317`:
44
+
45
+ ```bash
46
+ npx @angelitosystems/nest-devtools-cli
47
+ ```
48
+
49
+ ## Configuracion
50
+
51
+ ```ts
52
+ NestDevTools.init(app, {
53
+ project: 'catalog-api',
54
+ environment: 'development',
55
+ server: 'ws://localhost:4318',
56
+ capture: {
57
+ requests: true,
58
+ logs: true,
59
+ errors: true,
60
+ performance: true,
61
+ database: true,
62
+ websockets: true,
63
+ },
64
+ redact: ['customerSecret'],
65
+ allow: ['publicToken'],
66
+ });
67
+ ```
68
+
69
+ Opciones y variables de entorno principales:
70
+
71
+ | Opcion | Variable | Valor predeterminado |
72
+ |---|---|---|
73
+ | `enabled` | `NEST_DEVTOOLS_ENABLED` | Activo fuera de `production` |
74
+ | `server` | `NEST_DEVTOOLS_URL` | `ws://localhost:4318` |
75
+ | `project` | `NEST_DEVTOOLS_PROJECT` | Nombre del proyecto |
76
+ | `token` | `NEST_DEVTOOLS_TOKEN` | Sin token |
77
+ | `sampling` | `NEST_DEVTOOLS_SAMPLING` | `1` |
78
+
79
+ En produccion el SDK se desactiva por defecto. Activalo explicitamente solo si necesitas capturar datos alli y has revisado la configuracion de redaccion.
80
+
81
+ ## API adicional
82
+
83
+ ```ts
84
+ import {
85
+ NestDevTools,
86
+ captureError,
87
+ requestContext,
88
+ } from '@angelitosystems/nest-devtools';
89
+
90
+ captureError(new Error('Database unavailable'));
91
+ const requestId = requestContext().requestId();
92
+ ```
93
+
94
+ `NestDevTools.init()` devuelve un `InitResult` con `enabled`, `projectId`, `projectName`, `server` y, cuando corresponde, la razon de una desactivacion.
95
+
96
+ ## Desarrollo
97
+
98
+ ```bash
99
+ bun run --cwd packages/nestjs build
100
+ bun test packages/nestjs
101
+ ```
102
+
103
+ ## Licencia
104
+
105
+ MIT. Consulta la guia completa en [`docs/quick-start.md`](../../docs/quick-start.md) y [`docs/configuration.md`](../../docs/configuration.md).
package/dist/index.cjs CHANGED
@@ -262,6 +262,10 @@ var originalConsole = new import_console.Console({
262
262
  stderr: process.stderr,
263
263
  colorMode: "auto"
264
264
  });
265
+ function writeOriginalConsole(method, ...args) {
266
+ const fn = originalConsole[method];
267
+ if (fn) fn.apply(originalConsole, args);
268
+ }
265
269
  var ConsoleInstrumentation = class {
266
270
  constructor(ctx) {
267
271
  this.ctx = ctx;
@@ -693,6 +697,9 @@ var NestDevTools = class {
693
697
  if (config.capture.database) {
694
698
  registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());
695
699
  }
700
+ writeOriginalConsole("log", "[NestJS DevTools] SDK started");
701
+ writeOriginalConsole("log", ` SDK endpoint: ${config.server}`);
702
+ writeOriginalConsole("log", ` Dashboard: ${dashboardUrl(config.server)}`);
696
703
  return {
697
704
  enabled: true,
698
705
  projectId: config.projectId,
@@ -739,6 +746,20 @@ function detectRuntimeVersion() {
739
746
  const versions = process.versions;
740
747
  return versions["bun"] ?? versions["deno"] ?? process.version;
741
748
  }
749
+ function dashboardUrl(server) {
750
+ try {
751
+ const url = new URL(server);
752
+ url.protocol = url.protocol === "wss:" ? "https:" : "http:";
753
+ const port = Number(url.port);
754
+ url.port = String(Number.isFinite(port) && port > 0 ? port - 1 : 4317);
755
+ url.pathname = "";
756
+ url.search = "";
757
+ url.hash = "";
758
+ return url.toString().replace(/\/$/, "");
759
+ } catch {
760
+ return "http://localhost:4317";
761
+ }
762
+ }
742
763
 
743
764
  // src/index.ts
744
765
  var import_devtools_core8 = require("@angelitosystems/devtools-core");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sdk.ts","../src/instrumentation/http.ts","../src/emitter.ts","../src/instrumentation/timeline.ts","../src/instrumentation/console.ts","../src/instrumentation/nest-logger.ts","../src/instrumentation/exceptions.ts","../src/instrumentation/performance.ts","../src/instrumentation/app-explorer.ts","../src/instrumentation/websockets.ts","../src/instrumentation/database.ts","../src/detect.ts","../src/version.ts"],"sourcesContent":["/**\n * @angelitosystems/nest-devtools\n *\n * Drop-in real-time debugging and observability for NestJS.\n *\n * Usage:\n * import { NestDevTools } from '@angelitosystems/nest-devtools';\n * const app = await NestFactory.create(AppModule);\n * NestDevTools.init(app);\n */\nexport { NestDevTools, devtools } from './sdk';\nexport type { InitResult } from './sdk';\nexport { captureError } from './instrumentation/exceptions';\nexport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nexport { requestContext } from '@angelitosystems/devtools-core';\nexport type { RequestContext } from '@angelitosystems/devtools-core';\n","import { hostname } from 'os';\nimport { devtools as coreDevtools, resolveConfig } from '@angelitosystems/devtools-core';\nimport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nimport type { ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { HttpInstrumentation } from './instrumentation/http';\nimport { ConsoleInstrumentation } from './instrumentation/console';\nimport { LoggerInstrumentation } from './instrumentation/nest-logger';\nimport { ExceptionsInstrumentation, captureError } from './instrumentation/exceptions';\nimport { PerformanceInstrumentation } from './instrumentation/performance';\nimport { AppExplorer } from './instrumentation/app-explorer';\nimport { WebsocketInstrumentation } from './instrumentation/websockets';\nimport { DatabaseInstrumentation } from './instrumentation/database';\nimport { detectNestJsVersion } from './detect';\nimport { SDK_VERSION } from './version';\n\n/** Result of calling NestDevTools.init(). */\nexport interface InitResult {\n /** True when instrumentation is live. */\n enabled: boolean;\n /** Reason when partially or fully disabled. */\n reason?: 'disabled-by-config' | 'already-initialized' | 'no-http-adapter';\n projectId: string;\n projectName: string;\n server: string;\n}\n\n/**\n * Main entry point: `NestDevTools.init(app, config?)`.\n *\n * Never throws, never blocks startup, and disables itself in production\n * unless explicitly enabled.\n */\nexport class NestDevTools {\n private static readonly cleanups: Array<() => void> = [];\n private static initialized = false;\n\n /** Initialize DevTools for a NestJS application. One active instance per process. */\n static init(app: INestApplication, userConfig?: DevToolsUserConfig): InitResult {\n const config = resolveConfig(userConfig);\n const disabled: InitResult = {\n enabled: false,\n reason: 'disabled-by-config',\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n server: config.server,\n };\n\n if (this.initialized) return { ...disabled, reason: 'already-initialized' };\n if (!config.enabled) return disabled; // zero side effects: no patching, no sockets, no timers\n\n this.initialized = true;\n const registerCleanup = (fn: () => void) => this.cleanups.push(fn);\n\n const projectInfo: ProjectInfo = {\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n environment: config.environment,\n hostname: safeHostname(),\n port: null,\n pid: process.pid,\n runtime: detectRuntime(),\n runtimeVersion: detectRuntimeVersion(),\n nodeVersion: process.version,\n nestjsVersion: detectNestJsVersion(),\n sdkVersion: SDK_VERSION,\n };\n\n // transport is fully async: a missing server never affects startup\n coreDevtools.initialize({ config, projectInfo, registerCleanup });\n\n const adapter = app.getHttpAdapter();\n const httpReady = Boolean(adapter && ['http', 'express'].includes(adapter.getType()));\n\n // ---- HTTP instrumentation -------------------------------------------\n const http = new HttpInstrumentation({ config, projectInfo });\n registerCleanup(http.attach(app));\n\n // ---- console + NestJS Logger + global errors ------------------------\n registerCleanup(new ConsoleInstrumentation({ config, projectInfo }).attach());\n registerCleanup(new LoggerInstrumentation({ config, projectInfo }).attach());\n registerCleanup(ExceptionsInstrumentation.attach({ config, projectInfo }));\n\n // ---- performance sampling -------------------------------------------\n registerCleanup(new PerformanceInstrumentation({ config, projectInfo }).attach());\n\n // ---- application graph ----------------------------------------------\n registerCleanup(new AppExplorer({ config, projectInfo }).attach(app));\n\n // ---- websockets + database (best effort) ----------------------------\n if (config.capture.websockets) {\n registerCleanup(new WebsocketInstrumentation({ config, projectInfo }).attach());\n }\n if (config.capture.database) {\n registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());\n }\n\n return {\n enabled: true,\n projectId: config.projectId,\n projectName: projectInfo.projectName,\n server: config.server,\n ...(httpReady ? {} : { reason: 'no-http-adapter' as const }),\n };\n }\n\n /** Teardown everything (mostly useful in tests). */\n static destroy(): void {\n for (const cleanup of this.cleanups.splice(0)) {\n try {\n cleanup();\n } catch {\n /* ignore */\n }\n }\n this.initialized = false;\n coreDevtools.shutdown();\n }\n\n /** Whether the SDK is currently active in this process. */\n static isActive(): boolean {\n return this.initialized;\n }\n}\n\n/** Convenience functional alias: devtools.init(app). */\nexport const devtools = {\n init: NestDevTools.init.bind(NestDevTools),\n destroy: NestDevTools.destroy.bind(NestDevTools),\n isActive: NestDevTools.isActive.bind(NestDevTools),\n};\n\nfunction safeHostname(): string {\n try {\n return hostname();\n } catch {\n return 'unknown';\n }\n}\n\nfunction detectRuntime(): string {\n const versions = process.versions as Record<string, string | undefined>;\n if (versions['bun']) return 'bun';\n if (versions['deno']) return 'deno';\n return 'node';\n}\n\nfunction detectRuntimeVersion(): string {\n const versions = process.versions as Record<string, string | undefined>;\n return versions['bun'] ?? versions['deno'] ?? process.version;\n}\n\nexport { captureError };\n","import type { IncomingMessage, ServerResponse, Server as HttpServer } from 'http';\nimport { Redactor, randomId } from '@angelitosystems/devtools-protocol';\nimport type {\n ProjectInfo,\n RequestCompletedPayload,\n RequestStartedPayload,\n TimelineSpan,\n} from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\nimport { trackSpans } from './timeline';\n\n/** Shared context every instrumentation module receives. */\nexport interface InstrumentationContext {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n}\n\n/** Headers captured by default (denylist still applies). */\nconst INTERESTING_HEADERS = [\n 'content-type',\n 'content-length',\n 'accept',\n 'origin',\n 'referer',\n 'user-agent',\n 'x-forwarded-for',\n 'x-request-id',\n] as const;\n\ntype RequestListener = (req: IncomingMessage, res: ServerResponse) => void;\n\nconst WRAPPED = Symbol('nest-devtools.wrapped');\n\n/**\n * Instrument the HTTP server of a NestJS application.\n *\n * Covers both bootstrap orders without touching Node module internals:\n * - `NestDevTools.init(app)` after `app.listen()`: the server already exists\n * and is wrapped immediately.\n * - `NestDevTools.init(app)` before `app.listen()` (recommended): `app.listen`\n * is wrapped so the server is wrapped the moment it exists.\n */\nexport class HttpInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: InstrumentationContext) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Begin capturing HTTP requests. Returns a cleanup function. */\n attach(app: INestApplication): () => void {\n try {\n const adapter = app.getHttpAdapter();\n // 'http' = platform-default adapter, 'express' = @nestjs/platform-express\n if (!adapter || !['http', 'express'].includes(adapter.getType())) return () => {};\n\n const getServer = (): HttpServer | undefined =>\n (adapter as unknown as { getHttpServer?: () => HttpServer }).getHttpServer?.();\n\n // 1) server already exists (init called after listen)\n const existing = getServer();\n if (existing) {\n this.wrapServer(existing);\n return () => {};\n }\n\n // 2) init called before listen: wrap the server once listen() resolves\n const appLike = app as unknown as { listen: (...args: unknown[]) => unknown };\n const originalListen = appLike.listen.bind(app);\n const self = this;\n const patchedListen = (...args: unknown[]) => {\n const result = originalListen(...args);\n Promise.resolve(result)\n .then(() => {\n const server = getServer();\n if (server) self.wrapServer(server);\n })\n .catch(() => {\n /* listen failed — the app will surface its own error */\n });\n return result;\n };\n appLike.listen = patchedListen;\n\n return () => {\n appLike.listen = originalListen;\n };\n } catch {\n return () => {};\n }\n }\n\n /** Wrap the 'request' listeners of a server exactly once. */\n private wrapServer(server: HttpServer): void {\n const target = server as unknown as Record<symbol, unknown>;\n if (target[WRAPPED]) return;\n target[WRAPPED] = true;\n\n const self = this;\n const originalListeners = server.rawListeners('request') as RequestListener[];\n\n server.removeAllListeners('request');\n server.on('request', (req, res) => {\n self.instrumentRequest(req, res, () => {\n for (const listener of originalListeners) {\n listener.call(server, req, res);\n }\n });\n });\n }\n\n /** Wrap a single request lifecycle. */\n private instrumentRequest(req: IncomingMessage, res: ServerResponse, next: () => void): void {\n if (!this.ctx.config.capture.requests) {\n next();\n return;\n }\n\n const startedAt = Date.now();\n const requestId = randomId('req');\n const method = (req.method ?? 'GET').toUpperCase();\n const rawUrl = req.url ?? '/';\n const url = safeUrlPath(rawUrl);\n\n const spans: TimelineSpan[] = [];\n const unregister = trackSpans(requestId, spans);\n res.once('finish', unregister);\n\n const started: RequestStartedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n headers: this.collectHeaders(req),\n query: parseQuery(rawUrl),\n ip: clientIp(req),\n userAgent: asString(req.headers['user-agent']) || undefined,\n startedAt,\n };\n\n const middlewareSpan: TimelineSpan = {\n layer: 'middleware',\n label: `${method} ${url}`,\n duration: 0,\n startedAt,\n status: 'ok',\n };\n spans.push(middlewareSpan);\n\n const onFinished = () => {\n const finishedAt = Date.now();\n middlewareSpan.duration = Math.max(0, finishedAt - middlewareSpan.startedAt);\n middlewareSpan.status = res.statusCode >= 500 ? 'error' : 'ok';\n\n const responseSpan: TimelineSpan = {\n layer: 'response',\n label: 'response',\n duration: 0,\n startedAt: finishedAt,\n status: 'ok',\n };\n spans.push(responseSpan);\n\n const errored = res.statusCode >= 500;\n\n const completed: RequestCompletedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n statusCode: res.statusCode,\n duration: finishedAt - startedAt,\n startedAt,\n timeline: spans,\n query: parseQuery(rawUrl),\n errored,\n };\n\n emit('request.completed', completed);\n\n // NestJS exception filters turn controller errors into 5xx responses\n // without any process-level signal — surface them in the Error Explorer.\n if (errored) {\n emit('error.created', {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n name: 'HttpError',\n message: `${method} ${url} failed with status ${res.statusCode}`,\n fingerprint: httpErrorFingerprint(method, url, res.statusCode),\n request: { method, url, statusCode: res.statusCode },\n timestamp: finishedAt,\n });\n }\n };\n\n const context = requestContext();\n context.run({ requestId, method, url, startedAt }, () => {\n emit('request.started', started);\n res.once('finish', onFinished);\n next();\n });\n }\n\n private collectHeaders(req: IncomingMessage): Record<string, string> {\n const out: Record<string, string> = {};\n for (const key of INTERESTING_HEADERS) {\n const value = req.headers[key];\n if (value === undefined) continue;\n out[key] = this.redactor.isSensitive(key) ? '[REDACTED]' : asString(value).slice(0, 200);\n }\n return out;\n }\n}\n\nfunction asString(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value.join(', ');\n return value ?? '';\n}\n\n/** Stable fingerprint for framework-handled HTTP failures. */\nfunction httpErrorFingerprint(method: string, url: string, statusCode: number): string {\n const route = url.replace(/\\/\\d+(?=\\/|$)/g, '/:id'); // group /users/15 with /users/16\n const raw = `${method}::${route}::${statusCode}`;\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction safeUrlPath(raw: string): string {\n const index = raw.indexOf('?');\n return index === -1 ? raw : raw.slice(0, index);\n}\n\nfunction parseQuery(raw: string): Record<string, unknown> {\n const index = raw.indexOf('?');\n if (index === -1) return {};\n const out: Record<string, unknown> = {};\n for (const [key, value] of new URLSearchParams(raw.slice(index + 1))) {\n out[key] = value;\n }\n return out;\n}\n\nfunction clientIp(req: IncomingMessage): string | undefined {\n const forwarded = req.headers['x-forwarded-for'];\n if (typeof forwarded === 'string') return forwarded.split(',')[0]?.trim();\n return req.socket?.remoteAddress ?? undefined;\n}\n\nexport { safeUrlPath, parseQuery, clientIp };\n","import { devtools as coreDevtools } from '@angelitosystems/devtools-core';\nimport type { DevToolsEventMap, DevToolsEventName } from '@angelitosystems/devtools-protocol';\n\n/** Emit a typed protocol event to the DevTools server (fire-and-forget). */\nexport function emit<K extends DevToolsEventName>(event: K, payload: DevToolsEventMap[K]): void {\n try {\n coreDevtools.send(event, payload);\n } catch {\n /* instrumentation must never break the app */\n }\n}\n","import type { TimelineSpan } from '@angelitosystems/devtools-protocol';\n\n/** Create a started span inside a request's span list. */\nexport function startSpan(spans: TimelineSpan[], layer: string, label: string, detail?: string): TimelineSpan {\n const span: TimelineSpan = {\n layer,\n label,\n duration: 0,\n startedAt: Date.now(),\n status: 'ok',\n ...(detail !== undefined ? { detail } : {}),\n };\n spans.push(span);\n return span;\n}\n\n/** Finalize a span, computing its duration. */\nexport function endSpan(span: TimelineSpan, status?: 'ok' | 'error'): void {\n span.duration = Math.max(0, Date.now() - span.startedAt);\n if (status) span.status = status;\n}\n\n/**\n * Registry of active request timelines, keyed by requestId.\n * Lets deeper instrumentation (database, websockets) attach spans to the\n * request that caused them, using the AsyncLocalStorage request id.\n */\nconst recorders = new Map<string, TimelineSpan[]>();\n\n/** Register a request's span list. Returns an unregister callback. */\nexport function trackSpans(requestId: string, spans: TimelineSpan[]): () => void {\n recorders.set(requestId, spans);\n return () => recorders.delete(requestId);\n}\n\n/** Add an auto-ended span to a request if it is still active. */\nexport function recordSpan(requestId: string, layer: string, label: string, detail?: string, status?: 'ok' | 'error'): void {\n const spans = recorders.get(requestId);\n if (!spans) return;\n const span = startSpan(spans, layer, label, detail);\n endSpan(span, status);\n}\n","import { Console } from 'console';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport { resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\nconst METHODS = ['log', 'info', 'warn', 'error', 'debug'] as const;\ntype ConsoleMethod = (typeof METHODS)[number];\n\nconst LEVEL_BY_METHOD: Record<ConsoleMethod, LogLevel> = {\n log: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n debug: 'debug',\n};\n\n/** Original console bound directly to the process streams. */\nconst originalConsole = new Console({\n stdout: process.stdout,\n stderr: process.stderr,\n colorMode: 'auto',\n});\n\n/** Write through the untouched console (used by DevTools' own logging). */\nexport function writeOriginalConsole(method: ConsoleMethod, ...args: unknown[]): void {\n const fn = (originalConsole as unknown as Record<string, (...a: unknown[]) => void>)[method];\n if (fn) fn.apply(originalConsole, args);\n}\n\n/** Capture console output and mirror it to DevTools. */\nexport class ConsoleInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Patch console methods. Returns a restore function. */\n attach(): () => void {\n const self = this;\n const restores: Array<() => void> = [];\n\n for (const method of METHODS) {\n const original = (console as unknown as Record<string, unknown>)[method];\n if (typeof original !== 'function') continue;\n\n const patched = (...args: unknown[]) => {\n try {\n (original as (...a: unknown[]) => void).apply(console, args);\n } catch {\n /* never break host logging */\n }\n self.capture(method, args);\n };\n\n (console as unknown as Record<string, unknown>)[method] = patched;\n restores.push(() => {\n (console as unknown as Record<string, unknown>)[method] = original;\n });\n }\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n\n private capture(method: ConsoleMethod, args: unknown[]): void {\n if (!this.ctx.config.capture.logs) return;\n try {\n const level = LEVEL_BY_METHOD[method];\n const payload: LogPayload = {\n projectId: this.ctx.projectInfo.projectId,\n level,\n message: formatMessage(args, this.redactor),\n arguments: args.length > 0 ? (this.redactor.redact(args) as unknown[]) : undefined,\n stack: method === 'error' ? captureStack() : undefined,\n source: resolveSourceLocation(captureStack() ?? '', { skip: 0 }),\n context: undefined,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n if (method === 'error') payload.level = 'error';\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n }\n}\n\nfunction formatMessage(args: unknown[], redactor: Redactor): string {\n if (args.length === 0) return '';\n const first = args[0];\n if (typeof first === 'string') {\n return args.length === 1 ? redactor.redactString(first) : `${first} ${redactor.serialize(args.slice(1))}`;\n }\n return redactor.serialize(args);\n}\n\nfunction captureStack(): string | undefined {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return undefined;\n // drop the frames created by this helper\n return stack.split('\\n').slice(3).join('\\n');\n}\n","import { Logger } from '@nestjs/common';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\n/**\n * Captures NestJS framework logs (`new Logger('Ctx').log(...)` and the static\n * `Logger.log(...)` variants). Nest's Logger writes through process.stdout\n * internals, not console.*, so it needs its own hook.\n *\n * State is module-scoped on purpose: the patched methods are plain functions\n * and must never depend on class-instance `this` binding.\n */\nlet activeRedactor = new Redactor();\nlet activeConfig: DevToolsConfig | null = null;\nlet activeProjectId = '';\n\nfunction capture(level: LogLevel, message: unknown, context?: string, stack?: string): void {\n try {\n if (!activeConfig?.capture.logs) return;\n const text = typeof message === 'string' ? message : activeRedactor.serialize(message);\n const payload: LogPayload = {\n projectId: activeProjectId,\n level,\n message: activeRedactor.redactString(text),\n source: stack ? undefined : resolveSdkAwareLocation(),\n context,\n stack,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\n/** Captures NestJS Logger output and mirrors it to DevTools. */\nexport class LoggerInstrumentation {\n constructor(ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n activeRedactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n activeConfig = ctx.config;\n activeProjectId = ctx.projectInfo.projectId;\n }\n\n /** Patch Logger.prototype and the static Logger methods. Returns a restore function. */\n attach(): () => void {\n const restores: Array<() => void> = [];\n\n const patch = (owner: Record<string, unknown>, method: string, level: LogLevel, instance: boolean) => {\n const original = owner[method];\n if (typeof original !== 'function') return;\n\n owner[method] = function (this: unknown, message: unknown, ...rest: unknown[]) {\n const context = instance\n ? ((this as { context?: string } | undefined)?.context ?? (rest[0] as string | undefined))\n : (rest[0] as string | undefined);\n const stack = rest[1] as string | undefined;\n try {\n const result = (original as (...a: unknown[]) => unknown).apply(this, [message, ...rest]);\n capture(level, message, context, stack);\n return result;\n } catch (err) {\n capture(level, message, context, stack);\n throw err;\n }\n };\n\n restores.push(() => {\n owner[method] = original;\n });\n };\n\n // instance loggers: `new Logger('Ctx').log(...)` — the common case\n const proto = Logger.prototype as unknown as Record<string, unknown>;\n patch(proto, 'log', 'info', true);\n patch(proto, 'error', 'error', true);\n patch(proto, 'warn', 'warn', true);\n patch(proto, 'debug', 'debug', true);\n patch(proto, 'verbose', 'verbose', true);\n\n // static loggers: `Logger.log(...)`\n const statics = Logger as unknown as Record<string, unknown>;\n patch(statics, 'log', 'info', false);\n patch(statics, 'error', 'error', false);\n patch(statics, 'warn', 'warn', false);\n patch(statics, 'debug', 'debug', false);\n patch(statics, 'verbose', 'verbose', false);\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n}\n\nfunction resolveSdkAwareLocation(): LogPayload['source'] {\n try {\n const err = new Error();\n const stack = err.stack?.split('\\n').slice(3).join('\\n');\n return resolveSourceLocation(stack ?? '', { skip: 0 });\n } catch {\n return undefined;\n }\n}\n","import { basename } from 'path';\nimport type { ErrorPayload, ProjectInfo, SourceLocation } from '@angelitosystems/devtools-protocol';\nimport { requestContext, safeStringify, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\ntype InstrumentationCtx = {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n};\n\n/**\n * Global error capture via process-level hooks. Errors handled by NestJS\n * filters surface through request.completed; unexpected errors land here.\n */\nexport class ExceptionsInstrumentation {\n /** Attach process-level hooks. Returns a detach function. */\n static attach(ctx: InstrumentationCtx): () => void {\n const onUncaught = (error: unknown): void => {\n reportError(error, ctx, { source: 'uncaughtException' });\n };\n const onRejection = (reason: unknown): void => {\n reportError(reason, ctx, { source: 'unhandledRejection' });\n };\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n };\n }\n}\n\n/** Public helper: report an error manually from anywhere in the app. */\nexport function captureError(\n error: unknown,\n options?: { context?: string; controller?: string; service?: string },\n): void {\n reportError(error, undefined, options);\n}\n\nfunction reportError(\n error: unknown,\n ctx: InstrumentationCtx | undefined,\n options?: { context?: string; controller?: string; service?: string; source?: string },\n): void {\n try {\n if (ctx && !ctx.config.capture.errors) return;\n\n const normalized = normalizeError(error);\n const location = resolveSourceLocation(normalized.error ?? normalized.message, { skip: 1 });\n const projectId = ctx?.projectInfo.projectId ?? basename(process.cwd());\n\n const payload: ErrorPayload = {\n requestId: requestContext().requestId(),\n projectId,\n name: normalized.name,\n message: normalized.message,\n stack: normalized.error?.stack,\n source: location,\n fingerprint: fingerprint(normalized.name, normalized.message, location),\n context: options?.context ?? options?.source,\n request: currentRequestSummary(),\n controller: options?.controller,\n service: options?.service,\n timestamp: Date.now(),\n };\n\n emit('error.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\nfunction normalizeError(error: unknown): { error: Error | undefined; name: string; message: string } {\n if (error instanceof Error) {\n return { error, name: error.name, message: error.message };\n }\n if (typeof error === 'string') {\n return { error: undefined, name: 'Unknown', message: error };\n }\n if (error !== null && typeof error === 'object' && 'message' in error) {\n const record = error as Record<string, unknown>;\n return {\n error: undefined,\n name: typeof record['name'] === 'string' ? record['name'] : 'Error',\n message: String(record['message']),\n };\n }\n return { error: undefined, name: 'Unknown', message: safeStringify(error) };\n}\n\nfunction fingerprint(name: string, message: string, location?: SourceLocation): string {\n const raw = name + '::' + message + '::' + (location?.file ?? '') + ':' + String(location?.line ?? '');\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction currentRequestSummary(): { method: string; url: string } | undefined {\n const context = requestContext().current();\n if (!context?.method || !context?.url) return undefined;\n return { method: context.method, url: context.url };\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Performance instrumentation.\n *\n * Periodic CPU/memory/event-loop/latency sampling lives in core\n * (CoreDevtools.startPerformance) so it works even without an HTTP adapter.\n * This module exists as the capture-toggle boundary and future extension\n * point (gc hooks, histograms, cluster awareness).\n */\nexport class PerformanceInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op: sampling is owned by core. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { AppModuleNode, AppMemberNode, AppSnapshot, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\n\ninterface ContainerNode {\n id: string;\n name?: string;\n metatype?: Function;\n instance?: object;\n subtype?: 'httpController' | 'gateway';\n}\n\n/**\n * Explore the Nest container to build the module graph (modules, controllers,\n * providers, guards, pipes...). Best effort: any failure keeps the app safe.\n */\nexport class AppExplorer {\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {}\n\n /** Walk the container and emit app.snapshot. Returns a no-op cleanup. */\n attach(app: INestApplication): () => void {\n try {\n const snapshot = this.buildSnapshot(app);\n emit('app.snapshot', snapshot);\n } catch {\n /* best effort */\n }\n return () => {};\n }\n\n private buildSnapshot(app: INestApplication): AppSnapshot {\n const internal = (app as unknown as { container?: unknown }).container as\n | { getModules?: () => Map<string, ContainerNode> }\n | undefined;\n\n const modules: AppModuleNode[] = [];\n const modulesMap = internal?.getModules?.();\n if (modulesMap) {\n for (const [id, node] of modulesMap) {\n const moduleName = node.metatype?.name ?? String(id);\n const members = this.extractMembers(node);\n modules.push({\n name: moduleName,\n imports: [],\n controllers: members.controllers,\n providers: members.providers,\n exports: [],\n });\n }\n }\n\n return {\n projectId: this.ctx.projectInfo.projectId,\n projectName: this.ctx.projectInfo.projectName,\n modules,\n nestjsVersion: this.ctx.projectInfo.nestjsVersion,\n capturedAt: Date.now(),\n };\n }\n\n private extractMembers(node: ContainerNode): { controllers: AppMemberNode[]; providers: AppMemberNode[] } {\n const controllers: AppMemberNode[] = [];\n const providers: AppMemberNode[] = [];\n\n const providersMap = (node as unknown as { providers?: Map<string, unknown> }).providers;\n if (providersMap instanceof Map) {\n for (const [id, wrapper] of providersMap) {\n const member = this.memberFromWrapper(id, wrapper);\n if (!member) continue;\n if (wrapper && (wrapper as { subtype?: string }).subtype === 'httpController') {\n controllers.push(member);\n } else {\n providers.push(member);\n }\n }\n }\n\n return { controllers, providers };\n }\n\n private memberFromWrapper(id: string, wrapper: unknown): AppMemberNode | null {\n const w = wrapper as { name?: string; metatype?: Function; subtype?: string; instance?: Record<string, unknown> } | null;\n const name = w?.metatype?.name ?? (typeof id === 'string' ? id.replace(/^[A-Z_0-9]+:/, '') : 'unknown');\n const type = classify(name, w?.instance);\n return { name, type };\n }\n}\n\n/** Heuristic classification of providers into guards/interceptors/pipes/filters. */\nfunction classify(name: string, instance?: Record<string, unknown>): AppMemberNode['type'] {\n if (name.endsWith('Gateway')) return 'gateway';\n if (name.endsWith('Guard')) return 'guard';\n if (name.endsWith('Interceptor')) return 'interceptor';\n if (name.endsWith('Pipe')) return 'pipe';\n if (name.endsWith('Filter')) return 'filter';\n if (instance && typeof instance.canActivate === 'function') return 'guard';\n if (instance && typeof instance.intercept === 'function') return 'interceptor';\n if (instance && typeof instance.transform === 'function') return 'pipe';\n if (instance && typeof instance.catch === 'function') return 'filter';\n return 'provider';\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * WebSocket gateway instrumentation (v0.3 roadmap).\n *\n * Will introspect @WebSocketGateway() classes via the Nest container and wrap\n * gateway handlers. The placeholder keeps the init() wiring stable and\n * guarantees zero interference with host sockets.\n */\nexport class WebsocketInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Database instrumentation (v0.3 roadmap).\n *\n * Provider strategies will live here:\n * - Prisma: $extends / $use hooks\n * - TypeORM: DataSource QueryListener via subscriber\n * - Sequelize: sequelize.addHook\n * - MikroORM: EntityManager event subscriber\n *\n * All strategies must attach spans to the active request via trackSpans/\n * recordSpan and emit query.executed with redacted parameters.\n */\nexport class DatabaseInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nlet cached: string | null | undefined;\n\n/** Best-effort detection of the host app's @nestjs/core version. */\nexport function detectNestJsVersion(): string | null {\n if (cached !== undefined) return cached;\n cached = null;\n try {\n const candidates = [\n resolve(process.cwd(), 'node_modules/@nestjs/core/package.json'),\n // bun/pnpm layouts: walk up a couple of levels\n resolve(process.cwd(), '../../node_modules/@nestjs/core/package.json'),\n ];\n for (const path of candidates) {\n if (!existsSync(path)) continue;\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as { version?: string };\n if (pkg.version) {\n cached = pkg.version;\n break;\n }\n }\n } catch {\n cached = null;\n }\n return cached;\n}\n","/** SDK version reported to the DevTools server. Keep in sync with package.json. */\nexport const SDK_VERSION = '0.1.0';\n"],"mappings":"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","names":["import_devtools_core","import_devtools_core","coreDevtools","import_devtools_protocol","import_devtools_core","import_devtools_protocol","import_devtools_core","import_devtools_core","import_path","coreDevtools","import_devtools_core"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sdk.ts","../src/instrumentation/http.ts","../src/emitter.ts","../src/instrumentation/timeline.ts","../src/instrumentation/console.ts","../src/instrumentation/nest-logger.ts","../src/instrumentation/exceptions.ts","../src/instrumentation/performance.ts","../src/instrumentation/app-explorer.ts","../src/instrumentation/websockets.ts","../src/instrumentation/database.ts","../src/detect.ts","../src/version.ts"],"sourcesContent":["/**\n * @angelitosystems/nest-devtools\n *\n * Drop-in real-time debugging and observability for NestJS.\n *\n * Usage:\n * import { NestDevTools } from '@angelitosystems/nest-devtools';\n * const app = await NestFactory.create(AppModule);\n * NestDevTools.init(app);\n */\nexport { NestDevTools, devtools } from './sdk';\nexport type { InitResult } from './sdk';\nexport { captureError } from './instrumentation/exceptions';\nexport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nexport { requestContext } from '@angelitosystems/devtools-core';\nexport type { RequestContext } from '@angelitosystems/devtools-core';\n","import { hostname } from 'os';\nimport { devtools as coreDevtools, resolveConfig } from '@angelitosystems/devtools-core';\nimport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nimport type { ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { HttpInstrumentation } from './instrumentation/http';\nimport { ConsoleInstrumentation, writeOriginalConsole } from './instrumentation/console';\nimport { LoggerInstrumentation } from './instrumentation/nest-logger';\nimport { ExceptionsInstrumentation, captureError } from './instrumentation/exceptions';\nimport { PerformanceInstrumentation } from './instrumentation/performance';\nimport { AppExplorer } from './instrumentation/app-explorer';\nimport { WebsocketInstrumentation } from './instrumentation/websockets';\nimport { DatabaseInstrumentation } from './instrumentation/database';\nimport { detectNestJsVersion } from './detect';\nimport { SDK_VERSION } from './version';\n\n/** Result of calling NestDevTools.init(). */\nexport interface InitResult {\n /** True when instrumentation is live. */\n enabled: boolean;\n /** Reason when partially or fully disabled. */\n reason?: 'disabled-by-config' | 'already-initialized' | 'no-http-adapter';\n projectId: string;\n projectName: string;\n server: string;\n}\n\n/**\n * Main entry point: `NestDevTools.init(app, config?)`.\n *\n * Never throws, never blocks startup, and disables itself in production\n * unless explicitly enabled.\n */\nexport class NestDevTools {\n private static readonly cleanups: Array<() => void> = [];\n private static initialized = false;\n\n /** Initialize DevTools for a NestJS application. One active instance per process. */\n static init(app: INestApplication, userConfig?: DevToolsUserConfig): InitResult {\n const config = resolveConfig(userConfig);\n const disabled: InitResult = {\n enabled: false,\n reason: 'disabled-by-config',\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n server: config.server,\n };\n\n if (this.initialized) return { ...disabled, reason: 'already-initialized' };\n if (!config.enabled) return disabled; // zero side effects: no patching, no sockets, no timers\n\n this.initialized = true;\n const registerCleanup = (fn: () => void) => this.cleanups.push(fn);\n\n const projectInfo: ProjectInfo = {\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n environment: config.environment,\n hostname: safeHostname(),\n port: null,\n pid: process.pid,\n runtime: detectRuntime(),\n runtimeVersion: detectRuntimeVersion(),\n nodeVersion: process.version,\n nestjsVersion: detectNestJsVersion(),\n sdkVersion: SDK_VERSION,\n };\n\n // transport is fully async: a missing server never affects startup\n coreDevtools.initialize({ config, projectInfo, registerCleanup });\n\n const adapter = app.getHttpAdapter();\n const httpReady = Boolean(adapter && ['http', 'express'].includes(adapter.getType()));\n\n // ---- HTTP instrumentation -------------------------------------------\n const http = new HttpInstrumentation({ config, projectInfo });\n registerCleanup(http.attach(app));\n\n // ---- console + NestJS Logger + global errors ------------------------\n registerCleanup(new ConsoleInstrumentation({ config, projectInfo }).attach());\n registerCleanup(new LoggerInstrumentation({ config, projectInfo }).attach());\n registerCleanup(ExceptionsInstrumentation.attach({ config, projectInfo }));\n\n // ---- performance sampling -------------------------------------------\n registerCleanup(new PerformanceInstrumentation({ config, projectInfo }).attach());\n\n // ---- application graph ----------------------------------------------\n registerCleanup(new AppExplorer({ config, projectInfo }).attach(app));\n\n // ---- websockets + database (best effort) ----------------------------\n if (config.capture.websockets) {\n registerCleanup(new WebsocketInstrumentation({ config, projectInfo }).attach());\n }\n if (config.capture.database) {\n registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());\n }\n\n writeOriginalConsole('log', '[NestJS DevTools] SDK started');\n writeOriginalConsole('log', ` SDK endpoint: ${config.server}`);\n writeOriginalConsole('log', ` Dashboard: ${dashboardUrl(config.server)}`);\n\n return {\n enabled: true,\n projectId: config.projectId,\n projectName: projectInfo.projectName,\n server: config.server,\n ...(httpReady ? {} : { reason: 'no-http-adapter' as const }),\n };\n }\n\n /** Teardown everything (mostly useful in tests). */\n static destroy(): void {\n for (const cleanup of this.cleanups.splice(0)) {\n try {\n cleanup();\n } catch {\n /* ignore */\n }\n }\n this.initialized = false;\n coreDevtools.shutdown();\n }\n\n /** Whether the SDK is currently active in this process. */\n static isActive(): boolean {\n return this.initialized;\n }\n}\n\n/** Convenience functional alias: devtools.init(app). */\nexport const devtools = {\n init: NestDevTools.init.bind(NestDevTools),\n destroy: NestDevTools.destroy.bind(NestDevTools),\n isActive: NestDevTools.isActive.bind(NestDevTools),\n};\n\nfunction safeHostname(): string {\n try {\n return hostname();\n } catch {\n return 'unknown';\n }\n}\n\nfunction detectRuntime(): string {\n const versions = process.versions as Record<string, string | undefined>;\n if (versions['bun']) return 'bun';\n if (versions['deno']) return 'deno';\n return 'node';\n}\n\nfunction detectRuntimeVersion(): string {\n const versions = process.versions as Record<string, string | undefined>;\n return versions['bun'] ?? versions['deno'] ?? process.version;\n}\n\nfunction dashboardUrl(server: string): string {\n try {\n const url = new URL(server);\n url.protocol = url.protocol === 'wss:' ? 'https:' : 'http:';\n const port = Number(url.port);\n url.port = String(Number.isFinite(port) && port > 0 ? port - 1 : 4317);\n url.pathname = '';\n url.search = '';\n url.hash = '';\n return url.toString().replace(/\\/$/, '');\n } catch {\n return 'http://localhost:4317';\n }\n}\n\nexport { captureError };\n","import type { IncomingMessage, ServerResponse, Server as HttpServer } from 'http';\nimport { Redactor, randomId } from '@angelitosystems/devtools-protocol';\nimport type {\n ProjectInfo,\n RequestCompletedPayload,\n RequestStartedPayload,\n TimelineSpan,\n} from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\nimport { trackSpans } from './timeline';\n\n/** Shared context every instrumentation module receives. */\nexport interface InstrumentationContext {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n}\n\n/** Headers captured by default (denylist still applies). */\nconst INTERESTING_HEADERS = [\n 'content-type',\n 'content-length',\n 'accept',\n 'origin',\n 'referer',\n 'user-agent',\n 'x-forwarded-for',\n 'x-request-id',\n] as const;\n\ntype RequestListener = (req: IncomingMessage, res: ServerResponse) => void;\n\nconst WRAPPED = Symbol('nest-devtools.wrapped');\n\n/**\n * Instrument the HTTP server of a NestJS application.\n *\n * Covers both bootstrap orders without touching Node module internals:\n * - `NestDevTools.init(app)` after `app.listen()`: the server already exists\n * and is wrapped immediately.\n * - `NestDevTools.init(app)` before `app.listen()` (recommended): `app.listen`\n * is wrapped so the server is wrapped the moment it exists.\n */\nexport class HttpInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: InstrumentationContext) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Begin capturing HTTP requests. Returns a cleanup function. */\n attach(app: INestApplication): () => void {\n try {\n const adapter = app.getHttpAdapter();\n // 'http' = platform-default adapter, 'express' = @nestjs/platform-express\n if (!adapter || !['http', 'express'].includes(adapter.getType())) return () => {};\n\n const getServer = (): HttpServer | undefined =>\n (adapter as unknown as { getHttpServer?: () => HttpServer }).getHttpServer?.();\n\n // 1) server already exists (init called after listen)\n const existing = getServer();\n if (existing) {\n this.wrapServer(existing);\n return () => {};\n }\n\n // 2) init called before listen: wrap the server once listen() resolves\n const appLike = app as unknown as { listen: (...args: unknown[]) => unknown };\n const originalListen = appLike.listen.bind(app);\n const self = this;\n const patchedListen = (...args: unknown[]) => {\n const result = originalListen(...args);\n Promise.resolve(result)\n .then(() => {\n const server = getServer();\n if (server) self.wrapServer(server);\n })\n .catch(() => {\n /* listen failed — the app will surface its own error */\n });\n return result;\n };\n appLike.listen = patchedListen;\n\n return () => {\n appLike.listen = originalListen;\n };\n } catch {\n return () => {};\n }\n }\n\n /** Wrap the 'request' listeners of a server exactly once. */\n private wrapServer(server: HttpServer): void {\n const target = server as unknown as Record<symbol, unknown>;\n if (target[WRAPPED]) return;\n target[WRAPPED] = true;\n\n const self = this;\n const originalListeners = server.rawListeners('request') as RequestListener[];\n\n server.removeAllListeners('request');\n server.on('request', (req, res) => {\n self.instrumentRequest(req, res, () => {\n for (const listener of originalListeners) {\n listener.call(server, req, res);\n }\n });\n });\n }\n\n /** Wrap a single request lifecycle. */\n private instrumentRequest(req: IncomingMessage, res: ServerResponse, next: () => void): void {\n if (!this.ctx.config.capture.requests) {\n next();\n return;\n }\n\n const startedAt = Date.now();\n const requestId = randomId('req');\n const method = (req.method ?? 'GET').toUpperCase();\n const rawUrl = req.url ?? '/';\n const url = safeUrlPath(rawUrl);\n\n const spans: TimelineSpan[] = [];\n const unregister = trackSpans(requestId, spans);\n res.once('finish', unregister);\n\n const started: RequestStartedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n headers: this.collectHeaders(req),\n query: parseQuery(rawUrl),\n ip: clientIp(req),\n userAgent: asString(req.headers['user-agent']) || undefined,\n startedAt,\n };\n\n const middlewareSpan: TimelineSpan = {\n layer: 'middleware',\n label: `${method} ${url}`,\n duration: 0,\n startedAt,\n status: 'ok',\n };\n spans.push(middlewareSpan);\n\n const onFinished = () => {\n const finishedAt = Date.now();\n middlewareSpan.duration = Math.max(0, finishedAt - middlewareSpan.startedAt);\n middlewareSpan.status = res.statusCode >= 500 ? 'error' : 'ok';\n\n const responseSpan: TimelineSpan = {\n layer: 'response',\n label: 'response',\n duration: 0,\n startedAt: finishedAt,\n status: 'ok',\n };\n spans.push(responseSpan);\n\n const errored = res.statusCode >= 500;\n\n const completed: RequestCompletedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n statusCode: res.statusCode,\n duration: finishedAt - startedAt,\n startedAt,\n timeline: spans,\n query: parseQuery(rawUrl),\n errored,\n };\n\n emit('request.completed', completed);\n\n // NestJS exception filters turn controller errors into 5xx responses\n // without any process-level signal — surface them in the Error Explorer.\n if (errored) {\n emit('error.created', {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n name: 'HttpError',\n message: `${method} ${url} failed with status ${res.statusCode}`,\n fingerprint: httpErrorFingerprint(method, url, res.statusCode),\n request: { method, url, statusCode: res.statusCode },\n timestamp: finishedAt,\n });\n }\n };\n\n const context = requestContext();\n context.run({ requestId, method, url, startedAt }, () => {\n emit('request.started', started);\n res.once('finish', onFinished);\n next();\n });\n }\n\n private collectHeaders(req: IncomingMessage): Record<string, string> {\n const out: Record<string, string> = {};\n for (const key of INTERESTING_HEADERS) {\n const value = req.headers[key];\n if (value === undefined) continue;\n out[key] = this.redactor.isSensitive(key) ? '[REDACTED]' : asString(value).slice(0, 200);\n }\n return out;\n }\n}\n\nfunction asString(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value.join(', ');\n return value ?? '';\n}\n\n/** Stable fingerprint for framework-handled HTTP failures. */\nfunction httpErrorFingerprint(method: string, url: string, statusCode: number): string {\n const route = url.replace(/\\/\\d+(?=\\/|$)/g, '/:id'); // group /users/15 with /users/16\n const raw = `${method}::${route}::${statusCode}`;\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction safeUrlPath(raw: string): string {\n const index = raw.indexOf('?');\n return index === -1 ? raw : raw.slice(0, index);\n}\n\nfunction parseQuery(raw: string): Record<string, unknown> {\n const index = raw.indexOf('?');\n if (index === -1) return {};\n const out: Record<string, unknown> = {};\n for (const [key, value] of new URLSearchParams(raw.slice(index + 1))) {\n out[key] = value;\n }\n return out;\n}\n\nfunction clientIp(req: IncomingMessage): string | undefined {\n const forwarded = req.headers['x-forwarded-for'];\n if (typeof forwarded === 'string') return forwarded.split(',')[0]?.trim();\n return req.socket?.remoteAddress ?? undefined;\n}\n\nexport { safeUrlPath, parseQuery, clientIp };\n","import { devtools as coreDevtools } from '@angelitosystems/devtools-core';\nimport type { DevToolsEventMap, DevToolsEventName } from '@angelitosystems/devtools-protocol';\n\n/** Emit a typed protocol event to the DevTools server (fire-and-forget). */\nexport function emit<K extends DevToolsEventName>(event: K, payload: DevToolsEventMap[K]): void {\n try {\n coreDevtools.send(event, payload);\n } catch {\n /* instrumentation must never break the app */\n }\n}\n","import type { TimelineSpan } from '@angelitosystems/devtools-protocol';\n\n/** Create a started span inside a request's span list. */\nexport function startSpan(spans: TimelineSpan[], layer: string, label: string, detail?: string): TimelineSpan {\n const span: TimelineSpan = {\n layer,\n label,\n duration: 0,\n startedAt: Date.now(),\n status: 'ok',\n ...(detail !== undefined ? { detail } : {}),\n };\n spans.push(span);\n return span;\n}\n\n/** Finalize a span, computing its duration. */\nexport function endSpan(span: TimelineSpan, status?: 'ok' | 'error'): void {\n span.duration = Math.max(0, Date.now() - span.startedAt);\n if (status) span.status = status;\n}\n\n/**\n * Registry of active request timelines, keyed by requestId.\n * Lets deeper instrumentation (database, websockets) attach spans to the\n * request that caused them, using the AsyncLocalStorage request id.\n */\nconst recorders = new Map<string, TimelineSpan[]>();\n\n/** Register a request's span list. Returns an unregister callback. */\nexport function trackSpans(requestId: string, spans: TimelineSpan[]): () => void {\n recorders.set(requestId, spans);\n return () => recorders.delete(requestId);\n}\n\n/** Add an auto-ended span to a request if it is still active. */\nexport function recordSpan(requestId: string, layer: string, label: string, detail?: string, status?: 'ok' | 'error'): void {\n const spans = recorders.get(requestId);\n if (!spans) return;\n const span = startSpan(spans, layer, label, detail);\n endSpan(span, status);\n}\n","import { Console } from 'console';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport { resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\nconst METHODS = ['log', 'info', 'warn', 'error', 'debug'] as const;\ntype ConsoleMethod = (typeof METHODS)[number];\n\nconst LEVEL_BY_METHOD: Record<ConsoleMethod, LogLevel> = {\n log: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n debug: 'debug',\n};\n\n/** Original console bound directly to the process streams. */\nconst originalConsole = new Console({\n stdout: process.stdout,\n stderr: process.stderr,\n colorMode: 'auto',\n});\n\n/** Write through the untouched console (used by DevTools' own logging). */\nexport function writeOriginalConsole(method: ConsoleMethod, ...args: unknown[]): void {\n const fn = (originalConsole as unknown as Record<string, (...a: unknown[]) => void>)[method];\n if (fn) fn.apply(originalConsole, args);\n}\n\n/** Capture console output and mirror it to DevTools. */\nexport class ConsoleInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Patch console methods. Returns a restore function. */\n attach(): () => void {\n const self = this;\n const restores: Array<() => void> = [];\n\n for (const method of METHODS) {\n const original = (console as unknown as Record<string, unknown>)[method];\n if (typeof original !== 'function') continue;\n\n const patched = (...args: unknown[]) => {\n try {\n (original as (...a: unknown[]) => void).apply(console, args);\n } catch {\n /* never break host logging */\n }\n self.capture(method, args);\n };\n\n (console as unknown as Record<string, unknown>)[method] = patched;\n restores.push(() => {\n (console as unknown as Record<string, unknown>)[method] = original;\n });\n }\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n\n private capture(method: ConsoleMethod, args: unknown[]): void {\n if (!this.ctx.config.capture.logs) return;\n try {\n const level = LEVEL_BY_METHOD[method];\n const payload: LogPayload = {\n projectId: this.ctx.projectInfo.projectId,\n level,\n message: formatMessage(args, this.redactor),\n arguments: args.length > 0 ? (this.redactor.redact(args) as unknown[]) : undefined,\n stack: method === 'error' ? captureStack() : undefined,\n source: resolveSourceLocation(captureStack() ?? '', { skip: 0 }),\n context: undefined,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n if (method === 'error') payload.level = 'error';\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n }\n}\n\nfunction formatMessage(args: unknown[], redactor: Redactor): string {\n if (args.length === 0) return '';\n const first = args[0];\n if (typeof first === 'string') {\n return args.length === 1 ? redactor.redactString(first) : `${first} ${redactor.serialize(args.slice(1))}`;\n }\n return redactor.serialize(args);\n}\n\nfunction captureStack(): string | undefined {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return undefined;\n // drop the frames created by this helper\n return stack.split('\\n').slice(3).join('\\n');\n}\n","import { Logger } from '@nestjs/common';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\n/**\n * Captures NestJS framework logs (`new Logger('Ctx').log(...)` and the static\n * `Logger.log(...)` variants). Nest's Logger writes through process.stdout\n * internals, not console.*, so it needs its own hook.\n *\n * State is module-scoped on purpose: the patched methods are plain functions\n * and must never depend on class-instance `this` binding.\n */\nlet activeRedactor = new Redactor();\nlet activeConfig: DevToolsConfig | null = null;\nlet activeProjectId = '';\n\nfunction capture(level: LogLevel, message: unknown, context?: string, stack?: string): void {\n try {\n if (!activeConfig?.capture.logs) return;\n const text = typeof message === 'string' ? message : activeRedactor.serialize(message);\n const payload: LogPayload = {\n projectId: activeProjectId,\n level,\n message: activeRedactor.redactString(text),\n source: stack ? undefined : resolveSdkAwareLocation(),\n context,\n stack,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\n/** Captures NestJS Logger output and mirrors it to DevTools. */\nexport class LoggerInstrumentation {\n constructor(ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n activeRedactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n activeConfig = ctx.config;\n activeProjectId = ctx.projectInfo.projectId;\n }\n\n /** Patch Logger.prototype and the static Logger methods. Returns a restore function. */\n attach(): () => void {\n const restores: Array<() => void> = [];\n\n const patch = (owner: Record<string, unknown>, method: string, level: LogLevel, instance: boolean) => {\n const original = owner[method];\n if (typeof original !== 'function') return;\n\n owner[method] = function (this: unknown, message: unknown, ...rest: unknown[]) {\n const context = instance\n ? ((this as { context?: string } | undefined)?.context ?? (rest[0] as string | undefined))\n : (rest[0] as string | undefined);\n const stack = rest[1] as string | undefined;\n try {\n const result = (original as (...a: unknown[]) => unknown).apply(this, [message, ...rest]);\n capture(level, message, context, stack);\n return result;\n } catch (err) {\n capture(level, message, context, stack);\n throw err;\n }\n };\n\n restores.push(() => {\n owner[method] = original;\n });\n };\n\n // instance loggers: `new Logger('Ctx').log(...)` — the common case\n const proto = Logger.prototype as unknown as Record<string, unknown>;\n patch(proto, 'log', 'info', true);\n patch(proto, 'error', 'error', true);\n patch(proto, 'warn', 'warn', true);\n patch(proto, 'debug', 'debug', true);\n patch(proto, 'verbose', 'verbose', true);\n\n // static loggers: `Logger.log(...)`\n const statics = Logger as unknown as Record<string, unknown>;\n patch(statics, 'log', 'info', false);\n patch(statics, 'error', 'error', false);\n patch(statics, 'warn', 'warn', false);\n patch(statics, 'debug', 'debug', false);\n patch(statics, 'verbose', 'verbose', false);\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n}\n\nfunction resolveSdkAwareLocation(): LogPayload['source'] {\n try {\n const err = new Error();\n const stack = err.stack?.split('\\n').slice(3).join('\\n');\n return resolveSourceLocation(stack ?? '', { skip: 0 });\n } catch {\n return undefined;\n }\n}\n","import { basename } from 'path';\nimport type { ErrorPayload, ProjectInfo, SourceLocation } from '@angelitosystems/devtools-protocol';\nimport { requestContext, safeStringify, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\ntype InstrumentationCtx = {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n};\n\n/**\n * Global error capture via process-level hooks. Errors handled by NestJS\n * filters surface through request.completed; unexpected errors land here.\n */\nexport class ExceptionsInstrumentation {\n /** Attach process-level hooks. Returns a detach function. */\n static attach(ctx: InstrumentationCtx): () => void {\n const onUncaught = (error: unknown): void => {\n reportError(error, ctx, { source: 'uncaughtException' });\n };\n const onRejection = (reason: unknown): void => {\n reportError(reason, ctx, { source: 'unhandledRejection' });\n };\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n };\n }\n}\n\n/** Public helper: report an error manually from anywhere in the app. */\nexport function captureError(\n error: unknown,\n options?: { context?: string; controller?: string; service?: string },\n): void {\n reportError(error, undefined, options);\n}\n\nfunction reportError(\n error: unknown,\n ctx: InstrumentationCtx | undefined,\n options?: { context?: string; controller?: string; service?: string; source?: string },\n): void {\n try {\n if (ctx && !ctx.config.capture.errors) return;\n\n const normalized = normalizeError(error);\n const location = resolveSourceLocation(normalized.error ?? normalized.message, { skip: 1 });\n const projectId = ctx?.projectInfo.projectId ?? basename(process.cwd());\n\n const payload: ErrorPayload = {\n requestId: requestContext().requestId(),\n projectId,\n name: normalized.name,\n message: normalized.message,\n stack: normalized.error?.stack,\n source: location,\n fingerprint: fingerprint(normalized.name, normalized.message, location),\n context: options?.context ?? options?.source,\n request: currentRequestSummary(),\n controller: options?.controller,\n service: options?.service,\n timestamp: Date.now(),\n };\n\n emit('error.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\nfunction normalizeError(error: unknown): { error: Error | undefined; name: string; message: string } {\n if (error instanceof Error) {\n return { error, name: error.name, message: error.message };\n }\n if (typeof error === 'string') {\n return { error: undefined, name: 'Unknown', message: error };\n }\n if (error !== null && typeof error === 'object' && 'message' in error) {\n const record = error as Record<string, unknown>;\n return {\n error: undefined,\n name: typeof record['name'] === 'string' ? record['name'] : 'Error',\n message: String(record['message']),\n };\n }\n return { error: undefined, name: 'Unknown', message: safeStringify(error) };\n}\n\nfunction fingerprint(name: string, message: string, location?: SourceLocation): string {\n const raw = name + '::' + message + '::' + (location?.file ?? '') + ':' + String(location?.line ?? '');\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction currentRequestSummary(): { method: string; url: string } | undefined {\n const context = requestContext().current();\n if (!context?.method || !context?.url) return undefined;\n return { method: context.method, url: context.url };\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Performance instrumentation.\n *\n * Periodic CPU/memory/event-loop/latency sampling lives in core\n * (CoreDevtools.startPerformance) so it works even without an HTTP adapter.\n * This module exists as the capture-toggle boundary and future extension\n * point (gc hooks, histograms, cluster awareness).\n */\nexport class PerformanceInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op: sampling is owned by core. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { AppModuleNode, AppMemberNode, AppSnapshot, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\n\ninterface ContainerNode {\n id: string;\n name?: string;\n metatype?: Function;\n instance?: object;\n subtype?: 'httpController' | 'gateway';\n}\n\n/**\n * Explore the Nest container to build the module graph (modules, controllers,\n * providers, guards, pipes...). Best effort: any failure keeps the app safe.\n */\nexport class AppExplorer {\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {}\n\n /** Walk the container and emit app.snapshot. Returns a no-op cleanup. */\n attach(app: INestApplication): () => void {\n try {\n const snapshot = this.buildSnapshot(app);\n emit('app.snapshot', snapshot);\n } catch {\n /* best effort */\n }\n return () => {};\n }\n\n private buildSnapshot(app: INestApplication): AppSnapshot {\n const internal = (app as unknown as { container?: unknown }).container as\n | { getModules?: () => Map<string, ContainerNode> }\n | undefined;\n\n const modules: AppModuleNode[] = [];\n const modulesMap = internal?.getModules?.();\n if (modulesMap) {\n for (const [id, node] of modulesMap) {\n const moduleName = node.metatype?.name ?? String(id);\n const members = this.extractMembers(node);\n modules.push({\n name: moduleName,\n imports: [],\n controllers: members.controllers,\n providers: members.providers,\n exports: [],\n });\n }\n }\n\n return {\n projectId: this.ctx.projectInfo.projectId,\n projectName: this.ctx.projectInfo.projectName,\n modules,\n nestjsVersion: this.ctx.projectInfo.nestjsVersion,\n capturedAt: Date.now(),\n };\n }\n\n private extractMembers(node: ContainerNode): { controllers: AppMemberNode[]; providers: AppMemberNode[] } {\n const controllers: AppMemberNode[] = [];\n const providers: AppMemberNode[] = [];\n\n const providersMap = (node as unknown as { providers?: Map<string, unknown> }).providers;\n if (providersMap instanceof Map) {\n for (const [id, wrapper] of providersMap) {\n const member = this.memberFromWrapper(id, wrapper);\n if (!member) continue;\n if (wrapper && (wrapper as { subtype?: string }).subtype === 'httpController') {\n controllers.push(member);\n } else {\n providers.push(member);\n }\n }\n }\n\n return { controllers, providers };\n }\n\n private memberFromWrapper(id: string, wrapper: unknown): AppMemberNode | null {\n const w = wrapper as { name?: string; metatype?: Function; subtype?: string; instance?: Record<string, unknown> } | null;\n const name = w?.metatype?.name ?? (typeof id === 'string' ? id.replace(/^[A-Z_0-9]+:/, '') : 'unknown');\n const type = classify(name, w?.instance);\n return { name, type };\n }\n}\n\n/** Heuristic classification of providers into guards/interceptors/pipes/filters. */\nfunction classify(name: string, instance?: Record<string, unknown>): AppMemberNode['type'] {\n if (name.endsWith('Gateway')) return 'gateway';\n if (name.endsWith('Guard')) return 'guard';\n if (name.endsWith('Interceptor')) return 'interceptor';\n if (name.endsWith('Pipe')) return 'pipe';\n if (name.endsWith('Filter')) return 'filter';\n if (instance && typeof instance.canActivate === 'function') return 'guard';\n if (instance && typeof instance.intercept === 'function') return 'interceptor';\n if (instance && typeof instance.transform === 'function') return 'pipe';\n if (instance && typeof instance.catch === 'function') return 'filter';\n return 'provider';\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * WebSocket gateway instrumentation (v0.3 roadmap).\n *\n * Will introspect @WebSocketGateway() classes via the Nest container and wrap\n * gateway handlers. The placeholder keeps the init() wiring stable and\n * guarantees zero interference with host sockets.\n */\nexport class WebsocketInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Database instrumentation (v0.3 roadmap).\n *\n * Provider strategies will live here:\n * - Prisma: $extends / $use hooks\n * - TypeORM: DataSource QueryListener via subscriber\n * - Sequelize: sequelize.addHook\n * - MikroORM: EntityManager event subscriber\n *\n * All strategies must attach spans to the active request via trackSpans/\n * recordSpan and emit query.executed with redacted parameters.\n */\nexport class DatabaseInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nlet cached: string | null | undefined;\n\n/** Best-effort detection of the host app's @nestjs/core version. */\nexport function detectNestJsVersion(): string | null {\n if (cached !== undefined) return cached;\n cached = null;\n try {\n const candidates = [\n resolve(process.cwd(), 'node_modules/@nestjs/core/package.json'),\n // bun/pnpm layouts: walk up a couple of levels\n resolve(process.cwd(), '../../node_modules/@nestjs/core/package.json'),\n ];\n for (const path of candidates) {\n if (!existsSync(path)) continue;\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as { version?: string };\n if (pkg.version) {\n cached = pkg.version;\n break;\n }\n }\n } catch {\n cached = null;\n }\n return cached;\n}\n","/** SDK version reported to the DevTools server. Keep in sync with package.json. */\nexport const SDK_VERSION = '0.1.0';\n"],"mappings":"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","names":["import_devtools_core","import_devtools_core","coreDevtools","import_devtools_protocol","import_devtools_core","import_devtools_protocol","import_devtools_core","import_devtools_core","import_path","coreDevtools","import_devtools_core"]}
package/dist/index.js CHANGED
@@ -233,6 +233,10 @@ var originalConsole = new Console({
233
233
  stderr: process.stderr,
234
234
  colorMode: "auto"
235
235
  });
236
+ function writeOriginalConsole(method, ...args) {
237
+ const fn = originalConsole[method];
238
+ if (fn) fn.apply(originalConsole, args);
239
+ }
236
240
  var ConsoleInstrumentation = class {
237
241
  constructor(ctx) {
238
242
  this.ctx = ctx;
@@ -664,6 +668,9 @@ var NestDevTools = class {
664
668
  if (config.capture.database) {
665
669
  registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());
666
670
  }
671
+ writeOriginalConsole("log", "[NestJS DevTools] SDK started");
672
+ writeOriginalConsole("log", ` SDK endpoint: ${config.server}`);
673
+ writeOriginalConsole("log", ` Dashboard: ${dashboardUrl(config.server)}`);
667
674
  return {
668
675
  enabled: true,
669
676
  projectId: config.projectId,
@@ -710,6 +717,20 @@ function detectRuntimeVersion() {
710
717
  const versions = process.versions;
711
718
  return versions["bun"] ?? versions["deno"] ?? process.version;
712
719
  }
720
+ function dashboardUrl(server) {
721
+ try {
722
+ const url = new URL(server);
723
+ url.protocol = url.protocol === "wss:" ? "https:" : "http:";
724
+ const port = Number(url.port);
725
+ url.port = String(Number.isFinite(port) && port > 0 ? port - 1 : 4317);
726
+ url.pathname = "";
727
+ url.search = "";
728
+ url.hash = "";
729
+ return url.toString().replace(/\/$/, "");
730
+ } catch {
731
+ return "http://localhost:4317";
732
+ }
733
+ }
713
734
 
714
735
  // src/index.ts
715
736
  import { requestContext as requestContext5 } from "@angelitosystems/devtools-core";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk.ts","../src/instrumentation/http.ts","../src/emitter.ts","../src/instrumentation/timeline.ts","../src/instrumentation/console.ts","../src/instrumentation/nest-logger.ts","../src/instrumentation/exceptions.ts","../src/instrumentation/performance.ts","../src/instrumentation/app-explorer.ts","../src/instrumentation/websockets.ts","../src/instrumentation/database.ts","../src/detect.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { hostname } from 'os';\nimport { devtools as coreDevtools, resolveConfig } from '@angelitosystems/devtools-core';\nimport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nimport type { ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { HttpInstrumentation } from './instrumentation/http';\nimport { ConsoleInstrumentation } from './instrumentation/console';\nimport { LoggerInstrumentation } from './instrumentation/nest-logger';\nimport { ExceptionsInstrumentation, captureError } from './instrumentation/exceptions';\nimport { PerformanceInstrumentation } from './instrumentation/performance';\nimport { AppExplorer } from './instrumentation/app-explorer';\nimport { WebsocketInstrumentation } from './instrumentation/websockets';\nimport { DatabaseInstrumentation } from './instrumentation/database';\nimport { detectNestJsVersion } from './detect';\nimport { SDK_VERSION } from './version';\n\n/** Result of calling NestDevTools.init(). */\nexport interface InitResult {\n /** True when instrumentation is live. */\n enabled: boolean;\n /** Reason when partially or fully disabled. */\n reason?: 'disabled-by-config' | 'already-initialized' | 'no-http-adapter';\n projectId: string;\n projectName: string;\n server: string;\n}\n\n/**\n * Main entry point: `NestDevTools.init(app, config?)`.\n *\n * Never throws, never blocks startup, and disables itself in production\n * unless explicitly enabled.\n */\nexport class NestDevTools {\n private static readonly cleanups: Array<() => void> = [];\n private static initialized = false;\n\n /** Initialize DevTools for a NestJS application. One active instance per process. */\n static init(app: INestApplication, userConfig?: DevToolsUserConfig): InitResult {\n const config = resolveConfig(userConfig);\n const disabled: InitResult = {\n enabled: false,\n reason: 'disabled-by-config',\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n server: config.server,\n };\n\n if (this.initialized) return { ...disabled, reason: 'already-initialized' };\n if (!config.enabled) return disabled; // zero side effects: no patching, no sockets, no timers\n\n this.initialized = true;\n const registerCleanup = (fn: () => void) => this.cleanups.push(fn);\n\n const projectInfo: ProjectInfo = {\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n environment: config.environment,\n hostname: safeHostname(),\n port: null,\n pid: process.pid,\n runtime: detectRuntime(),\n runtimeVersion: detectRuntimeVersion(),\n nodeVersion: process.version,\n nestjsVersion: detectNestJsVersion(),\n sdkVersion: SDK_VERSION,\n };\n\n // transport is fully async: a missing server never affects startup\n coreDevtools.initialize({ config, projectInfo, registerCleanup });\n\n const adapter = app.getHttpAdapter();\n const httpReady = Boolean(adapter && ['http', 'express'].includes(adapter.getType()));\n\n // ---- HTTP instrumentation -------------------------------------------\n const http = new HttpInstrumentation({ config, projectInfo });\n registerCleanup(http.attach(app));\n\n // ---- console + NestJS Logger + global errors ------------------------\n registerCleanup(new ConsoleInstrumentation({ config, projectInfo }).attach());\n registerCleanup(new LoggerInstrumentation({ config, projectInfo }).attach());\n registerCleanup(ExceptionsInstrumentation.attach({ config, projectInfo }));\n\n // ---- performance sampling -------------------------------------------\n registerCleanup(new PerformanceInstrumentation({ config, projectInfo }).attach());\n\n // ---- application graph ----------------------------------------------\n registerCleanup(new AppExplorer({ config, projectInfo }).attach(app));\n\n // ---- websockets + database (best effort) ----------------------------\n if (config.capture.websockets) {\n registerCleanup(new WebsocketInstrumentation({ config, projectInfo }).attach());\n }\n if (config.capture.database) {\n registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());\n }\n\n return {\n enabled: true,\n projectId: config.projectId,\n projectName: projectInfo.projectName,\n server: config.server,\n ...(httpReady ? {} : { reason: 'no-http-adapter' as const }),\n };\n }\n\n /** Teardown everything (mostly useful in tests). */\n static destroy(): void {\n for (const cleanup of this.cleanups.splice(0)) {\n try {\n cleanup();\n } catch {\n /* ignore */\n }\n }\n this.initialized = false;\n coreDevtools.shutdown();\n }\n\n /** Whether the SDK is currently active in this process. */\n static isActive(): boolean {\n return this.initialized;\n }\n}\n\n/** Convenience functional alias: devtools.init(app). */\nexport const devtools = {\n init: NestDevTools.init.bind(NestDevTools),\n destroy: NestDevTools.destroy.bind(NestDevTools),\n isActive: NestDevTools.isActive.bind(NestDevTools),\n};\n\nfunction safeHostname(): string {\n try {\n return hostname();\n } catch {\n return 'unknown';\n }\n}\n\nfunction detectRuntime(): string {\n const versions = process.versions as Record<string, string | undefined>;\n if (versions['bun']) return 'bun';\n if (versions['deno']) return 'deno';\n return 'node';\n}\n\nfunction detectRuntimeVersion(): string {\n const versions = process.versions as Record<string, string | undefined>;\n return versions['bun'] ?? versions['deno'] ?? process.version;\n}\n\nexport { captureError };\n","import type { IncomingMessage, ServerResponse, Server as HttpServer } from 'http';\nimport { Redactor, randomId } from '@angelitosystems/devtools-protocol';\nimport type {\n ProjectInfo,\n RequestCompletedPayload,\n RequestStartedPayload,\n TimelineSpan,\n} from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\nimport { trackSpans } from './timeline';\n\n/** Shared context every instrumentation module receives. */\nexport interface InstrumentationContext {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n}\n\n/** Headers captured by default (denylist still applies). */\nconst INTERESTING_HEADERS = [\n 'content-type',\n 'content-length',\n 'accept',\n 'origin',\n 'referer',\n 'user-agent',\n 'x-forwarded-for',\n 'x-request-id',\n] as const;\n\ntype RequestListener = (req: IncomingMessage, res: ServerResponse) => void;\n\nconst WRAPPED = Symbol('nest-devtools.wrapped');\n\n/**\n * Instrument the HTTP server of a NestJS application.\n *\n * Covers both bootstrap orders without touching Node module internals:\n * - `NestDevTools.init(app)` after `app.listen()`: the server already exists\n * and is wrapped immediately.\n * - `NestDevTools.init(app)` before `app.listen()` (recommended): `app.listen`\n * is wrapped so the server is wrapped the moment it exists.\n */\nexport class HttpInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: InstrumentationContext) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Begin capturing HTTP requests. Returns a cleanup function. */\n attach(app: INestApplication): () => void {\n try {\n const adapter = app.getHttpAdapter();\n // 'http' = platform-default adapter, 'express' = @nestjs/platform-express\n if (!adapter || !['http', 'express'].includes(adapter.getType())) return () => {};\n\n const getServer = (): HttpServer | undefined =>\n (adapter as unknown as { getHttpServer?: () => HttpServer }).getHttpServer?.();\n\n // 1) server already exists (init called after listen)\n const existing = getServer();\n if (existing) {\n this.wrapServer(existing);\n return () => {};\n }\n\n // 2) init called before listen: wrap the server once listen() resolves\n const appLike = app as unknown as { listen: (...args: unknown[]) => unknown };\n const originalListen = appLike.listen.bind(app);\n const self = this;\n const patchedListen = (...args: unknown[]) => {\n const result = originalListen(...args);\n Promise.resolve(result)\n .then(() => {\n const server = getServer();\n if (server) self.wrapServer(server);\n })\n .catch(() => {\n /* listen failed — the app will surface its own error */\n });\n return result;\n };\n appLike.listen = patchedListen;\n\n return () => {\n appLike.listen = originalListen;\n };\n } catch {\n return () => {};\n }\n }\n\n /** Wrap the 'request' listeners of a server exactly once. */\n private wrapServer(server: HttpServer): void {\n const target = server as unknown as Record<symbol, unknown>;\n if (target[WRAPPED]) return;\n target[WRAPPED] = true;\n\n const self = this;\n const originalListeners = server.rawListeners('request') as RequestListener[];\n\n server.removeAllListeners('request');\n server.on('request', (req, res) => {\n self.instrumentRequest(req, res, () => {\n for (const listener of originalListeners) {\n listener.call(server, req, res);\n }\n });\n });\n }\n\n /** Wrap a single request lifecycle. */\n private instrumentRequest(req: IncomingMessage, res: ServerResponse, next: () => void): void {\n if (!this.ctx.config.capture.requests) {\n next();\n return;\n }\n\n const startedAt = Date.now();\n const requestId = randomId('req');\n const method = (req.method ?? 'GET').toUpperCase();\n const rawUrl = req.url ?? '/';\n const url = safeUrlPath(rawUrl);\n\n const spans: TimelineSpan[] = [];\n const unregister = trackSpans(requestId, spans);\n res.once('finish', unregister);\n\n const started: RequestStartedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n headers: this.collectHeaders(req),\n query: parseQuery(rawUrl),\n ip: clientIp(req),\n userAgent: asString(req.headers['user-agent']) || undefined,\n startedAt,\n };\n\n const middlewareSpan: TimelineSpan = {\n layer: 'middleware',\n label: `${method} ${url}`,\n duration: 0,\n startedAt,\n status: 'ok',\n };\n spans.push(middlewareSpan);\n\n const onFinished = () => {\n const finishedAt = Date.now();\n middlewareSpan.duration = Math.max(0, finishedAt - middlewareSpan.startedAt);\n middlewareSpan.status = res.statusCode >= 500 ? 'error' : 'ok';\n\n const responseSpan: TimelineSpan = {\n layer: 'response',\n label: 'response',\n duration: 0,\n startedAt: finishedAt,\n status: 'ok',\n };\n spans.push(responseSpan);\n\n const errored = res.statusCode >= 500;\n\n const completed: RequestCompletedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n statusCode: res.statusCode,\n duration: finishedAt - startedAt,\n startedAt,\n timeline: spans,\n query: parseQuery(rawUrl),\n errored,\n };\n\n emit('request.completed', completed);\n\n // NestJS exception filters turn controller errors into 5xx responses\n // without any process-level signal — surface them in the Error Explorer.\n if (errored) {\n emit('error.created', {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n name: 'HttpError',\n message: `${method} ${url} failed with status ${res.statusCode}`,\n fingerprint: httpErrorFingerprint(method, url, res.statusCode),\n request: { method, url, statusCode: res.statusCode },\n timestamp: finishedAt,\n });\n }\n };\n\n const context = requestContext();\n context.run({ requestId, method, url, startedAt }, () => {\n emit('request.started', started);\n res.once('finish', onFinished);\n next();\n });\n }\n\n private collectHeaders(req: IncomingMessage): Record<string, string> {\n const out: Record<string, string> = {};\n for (const key of INTERESTING_HEADERS) {\n const value = req.headers[key];\n if (value === undefined) continue;\n out[key] = this.redactor.isSensitive(key) ? '[REDACTED]' : asString(value).slice(0, 200);\n }\n return out;\n }\n}\n\nfunction asString(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value.join(', ');\n return value ?? '';\n}\n\n/** Stable fingerprint for framework-handled HTTP failures. */\nfunction httpErrorFingerprint(method: string, url: string, statusCode: number): string {\n const route = url.replace(/\\/\\d+(?=\\/|$)/g, '/:id'); // group /users/15 with /users/16\n const raw = `${method}::${route}::${statusCode}`;\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction safeUrlPath(raw: string): string {\n const index = raw.indexOf('?');\n return index === -1 ? raw : raw.slice(0, index);\n}\n\nfunction parseQuery(raw: string): Record<string, unknown> {\n const index = raw.indexOf('?');\n if (index === -1) return {};\n const out: Record<string, unknown> = {};\n for (const [key, value] of new URLSearchParams(raw.slice(index + 1))) {\n out[key] = value;\n }\n return out;\n}\n\nfunction clientIp(req: IncomingMessage): string | undefined {\n const forwarded = req.headers['x-forwarded-for'];\n if (typeof forwarded === 'string') return forwarded.split(',')[0]?.trim();\n return req.socket?.remoteAddress ?? undefined;\n}\n\nexport { safeUrlPath, parseQuery, clientIp };\n","import { devtools as coreDevtools } from '@angelitosystems/devtools-core';\nimport type { DevToolsEventMap, DevToolsEventName } from '@angelitosystems/devtools-protocol';\n\n/** Emit a typed protocol event to the DevTools server (fire-and-forget). */\nexport function emit<K extends DevToolsEventName>(event: K, payload: DevToolsEventMap[K]): void {\n try {\n coreDevtools.send(event, payload);\n } catch {\n /* instrumentation must never break the app */\n }\n}\n","import type { TimelineSpan } from '@angelitosystems/devtools-protocol';\n\n/** Create a started span inside a request's span list. */\nexport function startSpan(spans: TimelineSpan[], layer: string, label: string, detail?: string): TimelineSpan {\n const span: TimelineSpan = {\n layer,\n label,\n duration: 0,\n startedAt: Date.now(),\n status: 'ok',\n ...(detail !== undefined ? { detail } : {}),\n };\n spans.push(span);\n return span;\n}\n\n/** Finalize a span, computing its duration. */\nexport function endSpan(span: TimelineSpan, status?: 'ok' | 'error'): void {\n span.duration = Math.max(0, Date.now() - span.startedAt);\n if (status) span.status = status;\n}\n\n/**\n * Registry of active request timelines, keyed by requestId.\n * Lets deeper instrumentation (database, websockets) attach spans to the\n * request that caused them, using the AsyncLocalStorage request id.\n */\nconst recorders = new Map<string, TimelineSpan[]>();\n\n/** Register a request's span list. Returns an unregister callback. */\nexport function trackSpans(requestId: string, spans: TimelineSpan[]): () => void {\n recorders.set(requestId, spans);\n return () => recorders.delete(requestId);\n}\n\n/** Add an auto-ended span to a request if it is still active. */\nexport function recordSpan(requestId: string, layer: string, label: string, detail?: string, status?: 'ok' | 'error'): void {\n const spans = recorders.get(requestId);\n if (!spans) return;\n const span = startSpan(spans, layer, label, detail);\n endSpan(span, status);\n}\n","import { Console } from 'console';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport { resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\nconst METHODS = ['log', 'info', 'warn', 'error', 'debug'] as const;\ntype ConsoleMethod = (typeof METHODS)[number];\n\nconst LEVEL_BY_METHOD: Record<ConsoleMethod, LogLevel> = {\n log: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n debug: 'debug',\n};\n\n/** Original console bound directly to the process streams. */\nconst originalConsole = new Console({\n stdout: process.stdout,\n stderr: process.stderr,\n colorMode: 'auto',\n});\n\n/** Write through the untouched console (used by DevTools' own logging). */\nexport function writeOriginalConsole(method: ConsoleMethod, ...args: unknown[]): void {\n const fn = (originalConsole as unknown as Record<string, (...a: unknown[]) => void>)[method];\n if (fn) fn.apply(originalConsole, args);\n}\n\n/** Capture console output and mirror it to DevTools. */\nexport class ConsoleInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Patch console methods. Returns a restore function. */\n attach(): () => void {\n const self = this;\n const restores: Array<() => void> = [];\n\n for (const method of METHODS) {\n const original = (console as unknown as Record<string, unknown>)[method];\n if (typeof original !== 'function') continue;\n\n const patched = (...args: unknown[]) => {\n try {\n (original as (...a: unknown[]) => void).apply(console, args);\n } catch {\n /* never break host logging */\n }\n self.capture(method, args);\n };\n\n (console as unknown as Record<string, unknown>)[method] = patched;\n restores.push(() => {\n (console as unknown as Record<string, unknown>)[method] = original;\n });\n }\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n\n private capture(method: ConsoleMethod, args: unknown[]): void {\n if (!this.ctx.config.capture.logs) return;\n try {\n const level = LEVEL_BY_METHOD[method];\n const payload: LogPayload = {\n projectId: this.ctx.projectInfo.projectId,\n level,\n message: formatMessage(args, this.redactor),\n arguments: args.length > 0 ? (this.redactor.redact(args) as unknown[]) : undefined,\n stack: method === 'error' ? captureStack() : undefined,\n source: resolveSourceLocation(captureStack() ?? '', { skip: 0 }),\n context: undefined,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n if (method === 'error') payload.level = 'error';\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n }\n}\n\nfunction formatMessage(args: unknown[], redactor: Redactor): string {\n if (args.length === 0) return '';\n const first = args[0];\n if (typeof first === 'string') {\n return args.length === 1 ? redactor.redactString(first) : `${first} ${redactor.serialize(args.slice(1))}`;\n }\n return redactor.serialize(args);\n}\n\nfunction captureStack(): string | undefined {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return undefined;\n // drop the frames created by this helper\n return stack.split('\\n').slice(3).join('\\n');\n}\n","import { Logger } from '@nestjs/common';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\n/**\n * Captures NestJS framework logs (`new Logger('Ctx').log(...)` and the static\n * `Logger.log(...)` variants). Nest's Logger writes through process.stdout\n * internals, not console.*, so it needs its own hook.\n *\n * State is module-scoped on purpose: the patched methods are plain functions\n * and must never depend on class-instance `this` binding.\n */\nlet activeRedactor = new Redactor();\nlet activeConfig: DevToolsConfig | null = null;\nlet activeProjectId = '';\n\nfunction capture(level: LogLevel, message: unknown, context?: string, stack?: string): void {\n try {\n if (!activeConfig?.capture.logs) return;\n const text = typeof message === 'string' ? message : activeRedactor.serialize(message);\n const payload: LogPayload = {\n projectId: activeProjectId,\n level,\n message: activeRedactor.redactString(text),\n source: stack ? undefined : resolveSdkAwareLocation(),\n context,\n stack,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\n/** Captures NestJS Logger output and mirrors it to DevTools. */\nexport class LoggerInstrumentation {\n constructor(ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n activeRedactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n activeConfig = ctx.config;\n activeProjectId = ctx.projectInfo.projectId;\n }\n\n /** Patch Logger.prototype and the static Logger methods. Returns a restore function. */\n attach(): () => void {\n const restores: Array<() => void> = [];\n\n const patch = (owner: Record<string, unknown>, method: string, level: LogLevel, instance: boolean) => {\n const original = owner[method];\n if (typeof original !== 'function') return;\n\n owner[method] = function (this: unknown, message: unknown, ...rest: unknown[]) {\n const context = instance\n ? ((this as { context?: string } | undefined)?.context ?? (rest[0] as string | undefined))\n : (rest[0] as string | undefined);\n const stack = rest[1] as string | undefined;\n try {\n const result = (original as (...a: unknown[]) => unknown).apply(this, [message, ...rest]);\n capture(level, message, context, stack);\n return result;\n } catch (err) {\n capture(level, message, context, stack);\n throw err;\n }\n };\n\n restores.push(() => {\n owner[method] = original;\n });\n };\n\n // instance loggers: `new Logger('Ctx').log(...)` — the common case\n const proto = Logger.prototype as unknown as Record<string, unknown>;\n patch(proto, 'log', 'info', true);\n patch(proto, 'error', 'error', true);\n patch(proto, 'warn', 'warn', true);\n patch(proto, 'debug', 'debug', true);\n patch(proto, 'verbose', 'verbose', true);\n\n // static loggers: `Logger.log(...)`\n const statics = Logger as unknown as Record<string, unknown>;\n patch(statics, 'log', 'info', false);\n patch(statics, 'error', 'error', false);\n patch(statics, 'warn', 'warn', false);\n patch(statics, 'debug', 'debug', false);\n patch(statics, 'verbose', 'verbose', false);\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n}\n\nfunction resolveSdkAwareLocation(): LogPayload['source'] {\n try {\n const err = new Error();\n const stack = err.stack?.split('\\n').slice(3).join('\\n');\n return resolveSourceLocation(stack ?? '', { skip: 0 });\n } catch {\n return undefined;\n }\n}\n","import { basename } from 'path';\nimport type { ErrorPayload, ProjectInfo, SourceLocation } from '@angelitosystems/devtools-protocol';\nimport { requestContext, safeStringify, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\ntype InstrumentationCtx = {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n};\n\n/**\n * Global error capture via process-level hooks. Errors handled by NestJS\n * filters surface through request.completed; unexpected errors land here.\n */\nexport class ExceptionsInstrumentation {\n /** Attach process-level hooks. Returns a detach function. */\n static attach(ctx: InstrumentationCtx): () => void {\n const onUncaught = (error: unknown): void => {\n reportError(error, ctx, { source: 'uncaughtException' });\n };\n const onRejection = (reason: unknown): void => {\n reportError(reason, ctx, { source: 'unhandledRejection' });\n };\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n };\n }\n}\n\n/** Public helper: report an error manually from anywhere in the app. */\nexport function captureError(\n error: unknown,\n options?: { context?: string; controller?: string; service?: string },\n): void {\n reportError(error, undefined, options);\n}\n\nfunction reportError(\n error: unknown,\n ctx: InstrumentationCtx | undefined,\n options?: { context?: string; controller?: string; service?: string; source?: string },\n): void {\n try {\n if (ctx && !ctx.config.capture.errors) return;\n\n const normalized = normalizeError(error);\n const location = resolveSourceLocation(normalized.error ?? normalized.message, { skip: 1 });\n const projectId = ctx?.projectInfo.projectId ?? basename(process.cwd());\n\n const payload: ErrorPayload = {\n requestId: requestContext().requestId(),\n projectId,\n name: normalized.name,\n message: normalized.message,\n stack: normalized.error?.stack,\n source: location,\n fingerprint: fingerprint(normalized.name, normalized.message, location),\n context: options?.context ?? options?.source,\n request: currentRequestSummary(),\n controller: options?.controller,\n service: options?.service,\n timestamp: Date.now(),\n };\n\n emit('error.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\nfunction normalizeError(error: unknown): { error: Error | undefined; name: string; message: string } {\n if (error instanceof Error) {\n return { error, name: error.name, message: error.message };\n }\n if (typeof error === 'string') {\n return { error: undefined, name: 'Unknown', message: error };\n }\n if (error !== null && typeof error === 'object' && 'message' in error) {\n const record = error as Record<string, unknown>;\n return {\n error: undefined,\n name: typeof record['name'] === 'string' ? record['name'] : 'Error',\n message: String(record['message']),\n };\n }\n return { error: undefined, name: 'Unknown', message: safeStringify(error) };\n}\n\nfunction fingerprint(name: string, message: string, location?: SourceLocation): string {\n const raw = name + '::' + message + '::' + (location?.file ?? '') + ':' + String(location?.line ?? '');\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction currentRequestSummary(): { method: string; url: string } | undefined {\n const context = requestContext().current();\n if (!context?.method || !context?.url) return undefined;\n return { method: context.method, url: context.url };\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Performance instrumentation.\n *\n * Periodic CPU/memory/event-loop/latency sampling lives in core\n * (CoreDevtools.startPerformance) so it works even without an HTTP adapter.\n * This module exists as the capture-toggle boundary and future extension\n * point (gc hooks, histograms, cluster awareness).\n */\nexport class PerformanceInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op: sampling is owned by core. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { AppModuleNode, AppMemberNode, AppSnapshot, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\n\ninterface ContainerNode {\n id: string;\n name?: string;\n metatype?: Function;\n instance?: object;\n subtype?: 'httpController' | 'gateway';\n}\n\n/**\n * Explore the Nest container to build the module graph (modules, controllers,\n * providers, guards, pipes...). Best effort: any failure keeps the app safe.\n */\nexport class AppExplorer {\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {}\n\n /** Walk the container and emit app.snapshot. Returns a no-op cleanup. */\n attach(app: INestApplication): () => void {\n try {\n const snapshot = this.buildSnapshot(app);\n emit('app.snapshot', snapshot);\n } catch {\n /* best effort */\n }\n return () => {};\n }\n\n private buildSnapshot(app: INestApplication): AppSnapshot {\n const internal = (app as unknown as { container?: unknown }).container as\n | { getModules?: () => Map<string, ContainerNode> }\n | undefined;\n\n const modules: AppModuleNode[] = [];\n const modulesMap = internal?.getModules?.();\n if (modulesMap) {\n for (const [id, node] of modulesMap) {\n const moduleName = node.metatype?.name ?? String(id);\n const members = this.extractMembers(node);\n modules.push({\n name: moduleName,\n imports: [],\n controllers: members.controllers,\n providers: members.providers,\n exports: [],\n });\n }\n }\n\n return {\n projectId: this.ctx.projectInfo.projectId,\n projectName: this.ctx.projectInfo.projectName,\n modules,\n nestjsVersion: this.ctx.projectInfo.nestjsVersion,\n capturedAt: Date.now(),\n };\n }\n\n private extractMembers(node: ContainerNode): { controllers: AppMemberNode[]; providers: AppMemberNode[] } {\n const controllers: AppMemberNode[] = [];\n const providers: AppMemberNode[] = [];\n\n const providersMap = (node as unknown as { providers?: Map<string, unknown> }).providers;\n if (providersMap instanceof Map) {\n for (const [id, wrapper] of providersMap) {\n const member = this.memberFromWrapper(id, wrapper);\n if (!member) continue;\n if (wrapper && (wrapper as { subtype?: string }).subtype === 'httpController') {\n controllers.push(member);\n } else {\n providers.push(member);\n }\n }\n }\n\n return { controllers, providers };\n }\n\n private memberFromWrapper(id: string, wrapper: unknown): AppMemberNode | null {\n const w = wrapper as { name?: string; metatype?: Function; subtype?: string; instance?: Record<string, unknown> } | null;\n const name = w?.metatype?.name ?? (typeof id === 'string' ? id.replace(/^[A-Z_0-9]+:/, '') : 'unknown');\n const type = classify(name, w?.instance);\n return { name, type };\n }\n}\n\n/** Heuristic classification of providers into guards/interceptors/pipes/filters. */\nfunction classify(name: string, instance?: Record<string, unknown>): AppMemberNode['type'] {\n if (name.endsWith('Gateway')) return 'gateway';\n if (name.endsWith('Guard')) return 'guard';\n if (name.endsWith('Interceptor')) return 'interceptor';\n if (name.endsWith('Pipe')) return 'pipe';\n if (name.endsWith('Filter')) return 'filter';\n if (instance && typeof instance.canActivate === 'function') return 'guard';\n if (instance && typeof instance.intercept === 'function') return 'interceptor';\n if (instance && typeof instance.transform === 'function') return 'pipe';\n if (instance && typeof instance.catch === 'function') return 'filter';\n return 'provider';\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * WebSocket gateway instrumentation (v0.3 roadmap).\n *\n * Will introspect @WebSocketGateway() classes via the Nest container and wrap\n * gateway handlers. The placeholder keeps the init() wiring stable and\n * guarantees zero interference with host sockets.\n */\nexport class WebsocketInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Database instrumentation (v0.3 roadmap).\n *\n * Provider strategies will live here:\n * - Prisma: $extends / $use hooks\n * - TypeORM: DataSource QueryListener via subscriber\n * - Sequelize: sequelize.addHook\n * - MikroORM: EntityManager event subscriber\n *\n * All strategies must attach spans to the active request via trackSpans/\n * recordSpan and emit query.executed with redacted parameters.\n */\nexport class DatabaseInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nlet cached: string | null | undefined;\n\n/** Best-effort detection of the host app's @nestjs/core version. */\nexport function detectNestJsVersion(): string | null {\n if (cached !== undefined) return cached;\n cached = null;\n try {\n const candidates = [\n resolve(process.cwd(), 'node_modules/@nestjs/core/package.json'),\n // bun/pnpm layouts: walk up a couple of levels\n resolve(process.cwd(), '../../node_modules/@nestjs/core/package.json'),\n ];\n for (const path of candidates) {\n if (!existsSync(path)) continue;\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as { version?: string };\n if (pkg.version) {\n cached = pkg.version;\n break;\n }\n }\n } catch {\n cached = null;\n }\n return cached;\n}\n","/** SDK version reported to the DevTools server. Keep in sync with package.json. */\nexport const SDK_VERSION = '0.1.0';\n","/**\n * @angelitosystems/nest-devtools\n *\n * Drop-in real-time debugging and observability for NestJS.\n *\n * Usage:\n * import { NestDevTools } from '@angelitosystems/nest-devtools';\n * const app = await NestFactory.create(AppModule);\n * NestDevTools.init(app);\n */\nexport { NestDevTools, devtools } from './sdk';\nexport type { InitResult } from './sdk';\nexport { captureError } from './instrumentation/exceptions';\nexport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nexport { requestContext } from '@angelitosystems/devtools-core';\nexport type { RequestContext } from '@angelitosystems/devtools-core';\n"],"mappings":"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","names":["coreDevtools","Redactor","requestContext","Redactor","requestContext","Redactor","requestContext","resolveSourceLocation","Redactor","requestContext","resolveSourceLocation","requestContext","resolveSourceLocation","resolveSourceLocation","requestContext","coreDevtools","requestContext"]}
1
+ {"version":3,"sources":["../src/sdk.ts","../src/instrumentation/http.ts","../src/emitter.ts","../src/instrumentation/timeline.ts","../src/instrumentation/console.ts","../src/instrumentation/nest-logger.ts","../src/instrumentation/exceptions.ts","../src/instrumentation/performance.ts","../src/instrumentation/app-explorer.ts","../src/instrumentation/websockets.ts","../src/instrumentation/database.ts","../src/detect.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { hostname } from 'os';\nimport { devtools as coreDevtools, resolveConfig } from '@angelitosystems/devtools-core';\nimport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nimport type { ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { HttpInstrumentation } from './instrumentation/http';\nimport { ConsoleInstrumentation, writeOriginalConsole } from './instrumentation/console';\nimport { LoggerInstrumentation } from './instrumentation/nest-logger';\nimport { ExceptionsInstrumentation, captureError } from './instrumentation/exceptions';\nimport { PerformanceInstrumentation } from './instrumentation/performance';\nimport { AppExplorer } from './instrumentation/app-explorer';\nimport { WebsocketInstrumentation } from './instrumentation/websockets';\nimport { DatabaseInstrumentation } from './instrumentation/database';\nimport { detectNestJsVersion } from './detect';\nimport { SDK_VERSION } from './version';\n\n/** Result of calling NestDevTools.init(). */\nexport interface InitResult {\n /** True when instrumentation is live. */\n enabled: boolean;\n /** Reason when partially or fully disabled. */\n reason?: 'disabled-by-config' | 'already-initialized' | 'no-http-adapter';\n projectId: string;\n projectName: string;\n server: string;\n}\n\n/**\n * Main entry point: `NestDevTools.init(app, config?)`.\n *\n * Never throws, never blocks startup, and disables itself in production\n * unless explicitly enabled.\n */\nexport class NestDevTools {\n private static readonly cleanups: Array<() => void> = [];\n private static initialized = false;\n\n /** Initialize DevTools for a NestJS application. One active instance per process. */\n static init(app: INestApplication, userConfig?: DevToolsUserConfig): InitResult {\n const config = resolveConfig(userConfig);\n const disabled: InitResult = {\n enabled: false,\n reason: 'disabled-by-config',\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n server: config.server,\n };\n\n if (this.initialized) return { ...disabled, reason: 'already-initialized' };\n if (!config.enabled) return disabled; // zero side effects: no patching, no sockets, no timers\n\n this.initialized = true;\n const registerCleanup = (fn: () => void) => this.cleanups.push(fn);\n\n const projectInfo: ProjectInfo = {\n projectId: config.projectId,\n projectName: config.project ?? config.projectId,\n environment: config.environment,\n hostname: safeHostname(),\n port: null,\n pid: process.pid,\n runtime: detectRuntime(),\n runtimeVersion: detectRuntimeVersion(),\n nodeVersion: process.version,\n nestjsVersion: detectNestJsVersion(),\n sdkVersion: SDK_VERSION,\n };\n\n // transport is fully async: a missing server never affects startup\n coreDevtools.initialize({ config, projectInfo, registerCleanup });\n\n const adapter = app.getHttpAdapter();\n const httpReady = Boolean(adapter && ['http', 'express'].includes(adapter.getType()));\n\n // ---- HTTP instrumentation -------------------------------------------\n const http = new HttpInstrumentation({ config, projectInfo });\n registerCleanup(http.attach(app));\n\n // ---- console + NestJS Logger + global errors ------------------------\n registerCleanup(new ConsoleInstrumentation({ config, projectInfo }).attach());\n registerCleanup(new LoggerInstrumentation({ config, projectInfo }).attach());\n registerCleanup(ExceptionsInstrumentation.attach({ config, projectInfo }));\n\n // ---- performance sampling -------------------------------------------\n registerCleanup(new PerformanceInstrumentation({ config, projectInfo }).attach());\n\n // ---- application graph ----------------------------------------------\n registerCleanup(new AppExplorer({ config, projectInfo }).attach(app));\n\n // ---- websockets + database (best effort) ----------------------------\n if (config.capture.websockets) {\n registerCleanup(new WebsocketInstrumentation({ config, projectInfo }).attach());\n }\n if (config.capture.database) {\n registerCleanup(new DatabaseInstrumentation({ config, projectInfo }).attach());\n }\n\n writeOriginalConsole('log', '[NestJS DevTools] SDK started');\n writeOriginalConsole('log', ` SDK endpoint: ${config.server}`);\n writeOriginalConsole('log', ` Dashboard: ${dashboardUrl(config.server)}`);\n\n return {\n enabled: true,\n projectId: config.projectId,\n projectName: projectInfo.projectName,\n server: config.server,\n ...(httpReady ? {} : { reason: 'no-http-adapter' as const }),\n };\n }\n\n /** Teardown everything (mostly useful in tests). */\n static destroy(): void {\n for (const cleanup of this.cleanups.splice(0)) {\n try {\n cleanup();\n } catch {\n /* ignore */\n }\n }\n this.initialized = false;\n coreDevtools.shutdown();\n }\n\n /** Whether the SDK is currently active in this process. */\n static isActive(): boolean {\n return this.initialized;\n }\n}\n\n/** Convenience functional alias: devtools.init(app). */\nexport const devtools = {\n init: NestDevTools.init.bind(NestDevTools),\n destroy: NestDevTools.destroy.bind(NestDevTools),\n isActive: NestDevTools.isActive.bind(NestDevTools),\n};\n\nfunction safeHostname(): string {\n try {\n return hostname();\n } catch {\n return 'unknown';\n }\n}\n\nfunction detectRuntime(): string {\n const versions = process.versions as Record<string, string | undefined>;\n if (versions['bun']) return 'bun';\n if (versions['deno']) return 'deno';\n return 'node';\n}\n\nfunction detectRuntimeVersion(): string {\n const versions = process.versions as Record<string, string | undefined>;\n return versions['bun'] ?? versions['deno'] ?? process.version;\n}\n\nfunction dashboardUrl(server: string): string {\n try {\n const url = new URL(server);\n url.protocol = url.protocol === 'wss:' ? 'https:' : 'http:';\n const port = Number(url.port);\n url.port = String(Number.isFinite(port) && port > 0 ? port - 1 : 4317);\n url.pathname = '';\n url.search = '';\n url.hash = '';\n return url.toString().replace(/\\/$/, '');\n } catch {\n return 'http://localhost:4317';\n }\n}\n\nexport { captureError };\n","import type { IncomingMessage, ServerResponse, Server as HttpServer } from 'http';\nimport { Redactor, randomId } from '@angelitosystems/devtools-protocol';\nimport type {\n ProjectInfo,\n RequestCompletedPayload,\n RequestStartedPayload,\n TimelineSpan,\n} from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\nimport { trackSpans } from './timeline';\n\n/** Shared context every instrumentation module receives. */\nexport interface InstrumentationContext {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n}\n\n/** Headers captured by default (denylist still applies). */\nconst INTERESTING_HEADERS = [\n 'content-type',\n 'content-length',\n 'accept',\n 'origin',\n 'referer',\n 'user-agent',\n 'x-forwarded-for',\n 'x-request-id',\n] as const;\n\ntype RequestListener = (req: IncomingMessage, res: ServerResponse) => void;\n\nconst WRAPPED = Symbol('nest-devtools.wrapped');\n\n/**\n * Instrument the HTTP server of a NestJS application.\n *\n * Covers both bootstrap orders without touching Node module internals:\n * - `NestDevTools.init(app)` after `app.listen()`: the server already exists\n * and is wrapped immediately.\n * - `NestDevTools.init(app)` before `app.listen()` (recommended): `app.listen`\n * is wrapped so the server is wrapped the moment it exists.\n */\nexport class HttpInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: InstrumentationContext) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Begin capturing HTTP requests. Returns a cleanup function. */\n attach(app: INestApplication): () => void {\n try {\n const adapter = app.getHttpAdapter();\n // 'http' = platform-default adapter, 'express' = @nestjs/platform-express\n if (!adapter || !['http', 'express'].includes(adapter.getType())) return () => {};\n\n const getServer = (): HttpServer | undefined =>\n (adapter as unknown as { getHttpServer?: () => HttpServer }).getHttpServer?.();\n\n // 1) server already exists (init called after listen)\n const existing = getServer();\n if (existing) {\n this.wrapServer(existing);\n return () => {};\n }\n\n // 2) init called before listen: wrap the server once listen() resolves\n const appLike = app as unknown as { listen: (...args: unknown[]) => unknown };\n const originalListen = appLike.listen.bind(app);\n const self = this;\n const patchedListen = (...args: unknown[]) => {\n const result = originalListen(...args);\n Promise.resolve(result)\n .then(() => {\n const server = getServer();\n if (server) self.wrapServer(server);\n })\n .catch(() => {\n /* listen failed — the app will surface its own error */\n });\n return result;\n };\n appLike.listen = patchedListen;\n\n return () => {\n appLike.listen = originalListen;\n };\n } catch {\n return () => {};\n }\n }\n\n /** Wrap the 'request' listeners of a server exactly once. */\n private wrapServer(server: HttpServer): void {\n const target = server as unknown as Record<symbol, unknown>;\n if (target[WRAPPED]) return;\n target[WRAPPED] = true;\n\n const self = this;\n const originalListeners = server.rawListeners('request') as RequestListener[];\n\n server.removeAllListeners('request');\n server.on('request', (req, res) => {\n self.instrumentRequest(req, res, () => {\n for (const listener of originalListeners) {\n listener.call(server, req, res);\n }\n });\n });\n }\n\n /** Wrap a single request lifecycle. */\n private instrumentRequest(req: IncomingMessage, res: ServerResponse, next: () => void): void {\n if (!this.ctx.config.capture.requests) {\n next();\n return;\n }\n\n const startedAt = Date.now();\n const requestId = randomId('req');\n const method = (req.method ?? 'GET').toUpperCase();\n const rawUrl = req.url ?? '/';\n const url = safeUrlPath(rawUrl);\n\n const spans: TimelineSpan[] = [];\n const unregister = trackSpans(requestId, spans);\n res.once('finish', unregister);\n\n const started: RequestStartedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n headers: this.collectHeaders(req),\n query: parseQuery(rawUrl),\n ip: clientIp(req),\n userAgent: asString(req.headers['user-agent']) || undefined,\n startedAt,\n };\n\n const middlewareSpan: TimelineSpan = {\n layer: 'middleware',\n label: `${method} ${url}`,\n duration: 0,\n startedAt,\n status: 'ok',\n };\n spans.push(middlewareSpan);\n\n const onFinished = () => {\n const finishedAt = Date.now();\n middlewareSpan.duration = Math.max(0, finishedAt - middlewareSpan.startedAt);\n middlewareSpan.status = res.statusCode >= 500 ? 'error' : 'ok';\n\n const responseSpan: TimelineSpan = {\n layer: 'response',\n label: 'response',\n duration: 0,\n startedAt: finishedAt,\n status: 'ok',\n };\n spans.push(responseSpan);\n\n const errored = res.statusCode >= 500;\n\n const completed: RequestCompletedPayload = {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n method,\n url,\n statusCode: res.statusCode,\n duration: finishedAt - startedAt,\n startedAt,\n timeline: spans,\n query: parseQuery(rawUrl),\n errored,\n };\n\n emit('request.completed', completed);\n\n // NestJS exception filters turn controller errors into 5xx responses\n // without any process-level signal — surface them in the Error Explorer.\n if (errored) {\n emit('error.created', {\n requestId,\n projectId: this.ctx.projectInfo.projectId,\n name: 'HttpError',\n message: `${method} ${url} failed with status ${res.statusCode}`,\n fingerprint: httpErrorFingerprint(method, url, res.statusCode),\n request: { method, url, statusCode: res.statusCode },\n timestamp: finishedAt,\n });\n }\n };\n\n const context = requestContext();\n context.run({ requestId, method, url, startedAt }, () => {\n emit('request.started', started);\n res.once('finish', onFinished);\n next();\n });\n }\n\n private collectHeaders(req: IncomingMessage): Record<string, string> {\n const out: Record<string, string> = {};\n for (const key of INTERESTING_HEADERS) {\n const value = req.headers[key];\n if (value === undefined) continue;\n out[key] = this.redactor.isSensitive(key) ? '[REDACTED]' : asString(value).slice(0, 200);\n }\n return out;\n }\n}\n\nfunction asString(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value.join(', ');\n return value ?? '';\n}\n\n/** Stable fingerprint for framework-handled HTTP failures. */\nfunction httpErrorFingerprint(method: string, url: string, statusCode: number): string {\n const route = url.replace(/\\/\\d+(?=\\/|$)/g, '/:id'); // group /users/15 with /users/16\n const raw = `${method}::${route}::${statusCode}`;\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction safeUrlPath(raw: string): string {\n const index = raw.indexOf('?');\n return index === -1 ? raw : raw.slice(0, index);\n}\n\nfunction parseQuery(raw: string): Record<string, unknown> {\n const index = raw.indexOf('?');\n if (index === -1) return {};\n const out: Record<string, unknown> = {};\n for (const [key, value] of new URLSearchParams(raw.slice(index + 1))) {\n out[key] = value;\n }\n return out;\n}\n\nfunction clientIp(req: IncomingMessage): string | undefined {\n const forwarded = req.headers['x-forwarded-for'];\n if (typeof forwarded === 'string') return forwarded.split(',')[0]?.trim();\n return req.socket?.remoteAddress ?? undefined;\n}\n\nexport { safeUrlPath, parseQuery, clientIp };\n","import { devtools as coreDevtools } from '@angelitosystems/devtools-core';\nimport type { DevToolsEventMap, DevToolsEventName } from '@angelitosystems/devtools-protocol';\n\n/** Emit a typed protocol event to the DevTools server (fire-and-forget). */\nexport function emit<K extends DevToolsEventName>(event: K, payload: DevToolsEventMap[K]): void {\n try {\n coreDevtools.send(event, payload);\n } catch {\n /* instrumentation must never break the app */\n }\n}\n","import type { TimelineSpan } from '@angelitosystems/devtools-protocol';\n\n/** Create a started span inside a request's span list. */\nexport function startSpan(spans: TimelineSpan[], layer: string, label: string, detail?: string): TimelineSpan {\n const span: TimelineSpan = {\n layer,\n label,\n duration: 0,\n startedAt: Date.now(),\n status: 'ok',\n ...(detail !== undefined ? { detail } : {}),\n };\n spans.push(span);\n return span;\n}\n\n/** Finalize a span, computing its duration. */\nexport function endSpan(span: TimelineSpan, status?: 'ok' | 'error'): void {\n span.duration = Math.max(0, Date.now() - span.startedAt);\n if (status) span.status = status;\n}\n\n/**\n * Registry of active request timelines, keyed by requestId.\n * Lets deeper instrumentation (database, websockets) attach spans to the\n * request that caused them, using the AsyncLocalStorage request id.\n */\nconst recorders = new Map<string, TimelineSpan[]>();\n\n/** Register a request's span list. Returns an unregister callback. */\nexport function trackSpans(requestId: string, spans: TimelineSpan[]): () => void {\n recorders.set(requestId, spans);\n return () => recorders.delete(requestId);\n}\n\n/** Add an auto-ended span to a request if it is still active. */\nexport function recordSpan(requestId: string, layer: string, label: string, detail?: string, status?: 'ok' | 'error'): void {\n const spans = recorders.get(requestId);\n if (!spans) return;\n const span = startSpan(spans, layer, label, detail);\n endSpan(span, status);\n}\n","import { Console } from 'console';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport { resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\nconst METHODS = ['log', 'info', 'warn', 'error', 'debug'] as const;\ntype ConsoleMethod = (typeof METHODS)[number];\n\nconst LEVEL_BY_METHOD: Record<ConsoleMethod, LogLevel> = {\n log: 'info',\n info: 'info',\n warn: 'warn',\n error: 'error',\n debug: 'debug',\n};\n\n/** Original console bound directly to the process streams. */\nconst originalConsole = new Console({\n stdout: process.stdout,\n stderr: process.stderr,\n colorMode: 'auto',\n});\n\n/** Write through the untouched console (used by DevTools' own logging). */\nexport function writeOriginalConsole(method: ConsoleMethod, ...args: unknown[]): void {\n const fn = (originalConsole as unknown as Record<string, (...a: unknown[]) => void>)[method];\n if (fn) fn.apply(originalConsole, args);\n}\n\n/** Capture console output and mirror it to DevTools. */\nexport class ConsoleInstrumentation {\n private readonly redactor: Redactor;\n\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n this.redactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n }\n\n /** Patch console methods. Returns a restore function. */\n attach(): () => void {\n const self = this;\n const restores: Array<() => void> = [];\n\n for (const method of METHODS) {\n const original = (console as unknown as Record<string, unknown>)[method];\n if (typeof original !== 'function') continue;\n\n const patched = (...args: unknown[]) => {\n try {\n (original as (...a: unknown[]) => void).apply(console, args);\n } catch {\n /* never break host logging */\n }\n self.capture(method, args);\n };\n\n (console as unknown as Record<string, unknown>)[method] = patched;\n restores.push(() => {\n (console as unknown as Record<string, unknown>)[method] = original;\n });\n }\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n\n private capture(method: ConsoleMethod, args: unknown[]): void {\n if (!this.ctx.config.capture.logs) return;\n try {\n const level = LEVEL_BY_METHOD[method];\n const payload: LogPayload = {\n projectId: this.ctx.projectInfo.projectId,\n level,\n message: formatMessage(args, this.redactor),\n arguments: args.length > 0 ? (this.redactor.redact(args) as unknown[]) : undefined,\n stack: method === 'error' ? captureStack() : undefined,\n source: resolveSourceLocation(captureStack() ?? '', { skip: 0 }),\n context: undefined,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n if (method === 'error') payload.level = 'error';\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n }\n}\n\nfunction formatMessage(args: unknown[], redactor: Redactor): string {\n if (args.length === 0) return '';\n const first = args[0];\n if (typeof first === 'string') {\n return args.length === 1 ? redactor.redactString(first) : `${first} ${redactor.serialize(args.slice(1))}`;\n }\n return redactor.serialize(args);\n}\n\nfunction captureStack(): string | undefined {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return undefined;\n // drop the frames created by this helper\n return stack.split('\\n').slice(3).join('\\n');\n}\n","import { Logger } from '@nestjs/common';\nimport { Redactor } from '@angelitosystems/devtools-protocol';\nimport type { LogPayload, LogLevel, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport { requestContext, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\n/**\n * Captures NestJS framework logs (`new Logger('Ctx').log(...)` and the static\n * `Logger.log(...)` variants). Nest's Logger writes through process.stdout\n * internals, not console.*, so it needs its own hook.\n *\n * State is module-scoped on purpose: the patched methods are plain functions\n * and must never depend on class-instance `this` binding.\n */\nlet activeRedactor = new Redactor();\nlet activeConfig: DevToolsConfig | null = null;\nlet activeProjectId = '';\n\nfunction capture(level: LogLevel, message: unknown, context?: string, stack?: string): void {\n try {\n if (!activeConfig?.capture.logs) return;\n const text = typeof message === 'string' ? message : activeRedactor.serialize(message);\n const payload: LogPayload = {\n projectId: activeProjectId,\n level,\n message: activeRedactor.redactString(text),\n source: stack ? undefined : resolveSdkAwareLocation(),\n context,\n stack,\n processId: process.pid,\n requestId: requestContext().requestId(),\n timestamp: Date.now(),\n };\n emit('log.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\n/** Captures NestJS Logger output and mirrors it to DevTools. */\nexport class LoggerInstrumentation {\n constructor(ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {\n activeRedactor = new Redactor({\n redact: ctx.config.redact,\n allow: ctx.config.allow,\n maxBytes: ctx.config.maxPayloadBytes,\n });\n activeConfig = ctx.config;\n activeProjectId = ctx.projectInfo.projectId;\n }\n\n /** Patch Logger.prototype and the static Logger methods. Returns a restore function. */\n attach(): () => void {\n const restores: Array<() => void> = [];\n\n const patch = (owner: Record<string, unknown>, method: string, level: LogLevel, instance: boolean) => {\n const original = owner[method];\n if (typeof original !== 'function') return;\n\n owner[method] = function (this: unknown, message: unknown, ...rest: unknown[]) {\n const context = instance\n ? ((this as { context?: string } | undefined)?.context ?? (rest[0] as string | undefined))\n : (rest[0] as string | undefined);\n const stack = rest[1] as string | undefined;\n try {\n const result = (original as (...a: unknown[]) => unknown).apply(this, [message, ...rest]);\n capture(level, message, context, stack);\n return result;\n } catch (err) {\n capture(level, message, context, stack);\n throw err;\n }\n };\n\n restores.push(() => {\n owner[method] = original;\n });\n };\n\n // instance loggers: `new Logger('Ctx').log(...)` — the common case\n const proto = Logger.prototype as unknown as Record<string, unknown>;\n patch(proto, 'log', 'info', true);\n patch(proto, 'error', 'error', true);\n patch(proto, 'warn', 'warn', true);\n patch(proto, 'debug', 'debug', true);\n patch(proto, 'verbose', 'verbose', true);\n\n // static loggers: `Logger.log(...)`\n const statics = Logger as unknown as Record<string, unknown>;\n patch(statics, 'log', 'info', false);\n patch(statics, 'error', 'error', false);\n patch(statics, 'warn', 'warn', false);\n patch(statics, 'debug', 'debug', false);\n patch(statics, 'verbose', 'verbose', false);\n\n return () => {\n for (const restore of restores.splice(0)) restore();\n };\n }\n}\n\nfunction resolveSdkAwareLocation(): LogPayload['source'] {\n try {\n const err = new Error();\n const stack = err.stack?.split('\\n').slice(3).join('\\n');\n return resolveSourceLocation(stack ?? '', { skip: 0 });\n } catch {\n return undefined;\n }\n}\n","import { basename } from 'path';\nimport type { ErrorPayload, ProjectInfo, SourceLocation } from '@angelitosystems/devtools-protocol';\nimport { requestContext, safeStringify, resolveSourceLocation } from '@angelitosystems/devtools-core';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\n\nimport { emit } from '../emitter';\n\ntype InstrumentationCtx = {\n config: DevToolsConfig;\n projectInfo: ProjectInfo;\n};\n\n/**\n * Global error capture via process-level hooks. Errors handled by NestJS\n * filters surface through request.completed; unexpected errors land here.\n */\nexport class ExceptionsInstrumentation {\n /** Attach process-level hooks. Returns a detach function. */\n static attach(ctx: InstrumentationCtx): () => void {\n const onUncaught = (error: unknown): void => {\n reportError(error, ctx, { source: 'uncaughtException' });\n };\n const onRejection = (reason: unknown): void => {\n reportError(reason, ctx, { source: 'unhandledRejection' });\n };\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n };\n }\n}\n\n/** Public helper: report an error manually from anywhere in the app. */\nexport function captureError(\n error: unknown,\n options?: { context?: string; controller?: string; service?: string },\n): void {\n reportError(error, undefined, options);\n}\n\nfunction reportError(\n error: unknown,\n ctx: InstrumentationCtx | undefined,\n options?: { context?: string; controller?: string; service?: string; source?: string },\n): void {\n try {\n if (ctx && !ctx.config.capture.errors) return;\n\n const normalized = normalizeError(error);\n const location = resolveSourceLocation(normalized.error ?? normalized.message, { skip: 1 });\n const projectId = ctx?.projectInfo.projectId ?? basename(process.cwd());\n\n const payload: ErrorPayload = {\n requestId: requestContext().requestId(),\n projectId,\n name: normalized.name,\n message: normalized.message,\n stack: normalized.error?.stack,\n source: location,\n fingerprint: fingerprint(normalized.name, normalized.message, location),\n context: options?.context ?? options?.source,\n request: currentRequestSummary(),\n controller: options?.controller,\n service: options?.service,\n timestamp: Date.now(),\n };\n\n emit('error.created', payload);\n } catch {\n /* never propagate */\n }\n}\n\nfunction normalizeError(error: unknown): { error: Error | undefined; name: string; message: string } {\n if (error instanceof Error) {\n return { error, name: error.name, message: error.message };\n }\n if (typeof error === 'string') {\n return { error: undefined, name: 'Unknown', message: error };\n }\n if (error !== null && typeof error === 'object' && 'message' in error) {\n const record = error as Record<string, unknown>;\n return {\n error: undefined,\n name: typeof record['name'] === 'string' ? record['name'] : 'Error',\n message: String(record['message']),\n };\n }\n return { error: undefined, name: 'Unknown', message: safeStringify(error) };\n}\n\nfunction fingerprint(name: string, message: string, location?: SourceLocation): string {\n const raw = name + '::' + message + '::' + (location?.file ?? '') + ':' + String(location?.line ?? '');\n let hash = 0;\n for (let i = 0; i < raw.length; i++) {\n hash = (hash * 31 + raw.charCodeAt(i)) >>> 0;\n }\n return hash.toString(36).padStart(7, '0');\n}\n\nfunction currentRequestSummary(): { method: string; url: string } | undefined {\n const context = requestContext().current();\n if (!context?.method || !context?.url) return undefined;\n return { method: context.method, url: context.url };\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Performance instrumentation.\n *\n * Periodic CPU/memory/event-loop/latency sampling lives in core\n * (CoreDevtools.startPerformance) so it works even without an HTTP adapter.\n * This module exists as the capture-toggle boundary and future extension\n * point (gc hooks, histograms, cluster awareness).\n */\nexport class PerformanceInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op: sampling is owned by core. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { AppModuleNode, AppMemberNode, AppSnapshot, ProjectInfo } from '@angelitosystems/devtools-protocol';\nimport type { DevToolsConfig } from '@angelitosystems/devtools-core';\nimport type { INestApplication } from '@nestjs/common';\n\nimport { emit } from '../emitter';\n\ninterface ContainerNode {\n id: string;\n name?: string;\n metatype?: Function;\n instance?: object;\n subtype?: 'httpController' | 'gateway';\n}\n\n/**\n * Explore the Nest container to build the module graph (modules, controllers,\n * providers, guards, pipes...). Best effort: any failure keeps the app safe.\n */\nexport class AppExplorer {\n constructor(private readonly ctx: { config: DevToolsConfig; projectInfo: ProjectInfo }) {}\n\n /** Walk the container and emit app.snapshot. Returns a no-op cleanup. */\n attach(app: INestApplication): () => void {\n try {\n const snapshot = this.buildSnapshot(app);\n emit('app.snapshot', snapshot);\n } catch {\n /* best effort */\n }\n return () => {};\n }\n\n private buildSnapshot(app: INestApplication): AppSnapshot {\n const internal = (app as unknown as { container?: unknown }).container as\n | { getModules?: () => Map<string, ContainerNode> }\n | undefined;\n\n const modules: AppModuleNode[] = [];\n const modulesMap = internal?.getModules?.();\n if (modulesMap) {\n for (const [id, node] of modulesMap) {\n const moduleName = node.metatype?.name ?? String(id);\n const members = this.extractMembers(node);\n modules.push({\n name: moduleName,\n imports: [],\n controllers: members.controllers,\n providers: members.providers,\n exports: [],\n });\n }\n }\n\n return {\n projectId: this.ctx.projectInfo.projectId,\n projectName: this.ctx.projectInfo.projectName,\n modules,\n nestjsVersion: this.ctx.projectInfo.nestjsVersion,\n capturedAt: Date.now(),\n };\n }\n\n private extractMembers(node: ContainerNode): { controllers: AppMemberNode[]; providers: AppMemberNode[] } {\n const controllers: AppMemberNode[] = [];\n const providers: AppMemberNode[] = [];\n\n const providersMap = (node as unknown as { providers?: Map<string, unknown> }).providers;\n if (providersMap instanceof Map) {\n for (const [id, wrapper] of providersMap) {\n const member = this.memberFromWrapper(id, wrapper);\n if (!member) continue;\n if (wrapper && (wrapper as { subtype?: string }).subtype === 'httpController') {\n controllers.push(member);\n } else {\n providers.push(member);\n }\n }\n }\n\n return { controllers, providers };\n }\n\n private memberFromWrapper(id: string, wrapper: unknown): AppMemberNode | null {\n const w = wrapper as { name?: string; metatype?: Function; subtype?: string; instance?: Record<string, unknown> } | null;\n const name = w?.metatype?.name ?? (typeof id === 'string' ? id.replace(/^[A-Z_0-9]+:/, '') : 'unknown');\n const type = classify(name, w?.instance);\n return { name, type };\n }\n}\n\n/** Heuristic classification of providers into guards/interceptors/pipes/filters. */\nfunction classify(name: string, instance?: Record<string, unknown>): AppMemberNode['type'] {\n if (name.endsWith('Gateway')) return 'gateway';\n if (name.endsWith('Guard')) return 'guard';\n if (name.endsWith('Interceptor')) return 'interceptor';\n if (name.endsWith('Pipe')) return 'pipe';\n if (name.endsWith('Filter')) return 'filter';\n if (instance && typeof instance.canActivate === 'function') return 'guard';\n if (instance && typeof instance.intercept === 'function') return 'interceptor';\n if (instance && typeof instance.transform === 'function') return 'pipe';\n if (instance && typeof instance.catch === 'function') return 'filter';\n return 'provider';\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * WebSocket gateway instrumentation (v0.3 roadmap).\n *\n * Will introspect @WebSocketGateway() classes via the Nest container and wrap\n * gateway handlers. The placeholder keeps the init() wiring stable and\n * guarantees zero interference with host sockets.\n */\nexport class WebsocketInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import type { InstrumentationContext } from './http';\n\n/**\n * Database instrumentation (v0.3 roadmap).\n *\n * Provider strategies will live here:\n * - Prisma: $extends / $use hooks\n * - TypeORM: DataSource QueryListener via subscriber\n * - Sequelize: sequelize.addHook\n * - MikroORM: EntityManager event subscriber\n *\n * All strategies must attach spans to the active request via trackSpans/\n * recordSpan and emit query.executed with redacted parameters.\n */\nexport class DatabaseInstrumentation {\n constructor(private readonly ctx: InstrumentationContext) {}\n\n /** No-op for now. Returns a no-op cleanup. */\n attach(): () => void {\n void this.ctx;\n return () => {};\n }\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nlet cached: string | null | undefined;\n\n/** Best-effort detection of the host app's @nestjs/core version. */\nexport function detectNestJsVersion(): string | null {\n if (cached !== undefined) return cached;\n cached = null;\n try {\n const candidates = [\n resolve(process.cwd(), 'node_modules/@nestjs/core/package.json'),\n // bun/pnpm layouts: walk up a couple of levels\n resolve(process.cwd(), '../../node_modules/@nestjs/core/package.json'),\n ];\n for (const path of candidates) {\n if (!existsSync(path)) continue;\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as { version?: string };\n if (pkg.version) {\n cached = pkg.version;\n break;\n }\n }\n } catch {\n cached = null;\n }\n return cached;\n}\n","/** SDK version reported to the DevTools server. Keep in sync with package.json. */\nexport const SDK_VERSION = '0.1.0';\n","/**\n * @angelitosystems/nest-devtools\n *\n * Drop-in real-time debugging and observability for NestJS.\n *\n * Usage:\n * import { NestDevTools } from '@angelitosystems/nest-devtools';\n * const app = await NestFactory.create(AppModule);\n * NestDevTools.init(app);\n */\nexport { NestDevTools, devtools } from './sdk';\nexport type { InitResult } from './sdk';\nexport { captureError } from './instrumentation/exceptions';\nexport type { DevToolsUserConfig } from '@angelitosystems/devtools-core';\nexport { requestContext } from '@angelitosystems/devtools-core';\nexport type { RequestContext } from '@angelitosystems/devtools-core';\n"],"mappings":"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","names":["coreDevtools","Redactor","requestContext","Redactor","requestContext","Redactor","requestContext","resolveSourceLocation","Redactor","requestContext","resolveSourceLocation","requestContext","resolveSourceLocation","resolveSourceLocation","requestContext","coreDevtools","requestContext"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angelitosystems/nest-devtools",
3
- "version": "0.1.0",
3
+ "version": "1.0.2",
4
4
  "description": "One-line real-time debugging and observability for NestJS applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,12 +32,12 @@
32
32
  "websocket"
33
33
  ],
34
34
  "dependencies": {
35
- "@angelitosystems/devtools-core": "^0.1.0",
36
- "@angelitosystems/devtools-protocol": "^0.1.0"
35
+ "@angelitosystems/devtools-core": "1.0.2",
36
+ "@angelitosystems/devtools-protocol": "1.0.2"
37
37
  },
38
38
  "peerDependencies": {
39
- "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0",
40
- "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0",
39
+ "@nestjs/common": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0",
40
+ "@nestjs/core": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0",
41
41
  "reflect-metadata": "^0.1.12 || ^0.2.0",
42
42
  "rxjs": "^7.1.0"
43
43
  },
@@ -47,10 +47,10 @@
47
47
  }
48
48
  },
49
49
  "devDependencies": {
50
- "@nestjs/common": "^11.0.0",
51
- "@nestjs/core": "^11.0.0",
52
- "@nestjs/platform-express": "^11.0.0",
53
- "@nestjs/testing": "^11.0.0",
50
+ "@nestjs/common": "^12.0.1",
51
+ "@nestjs/core": "^12.0.1",
52
+ "@nestjs/platform-express": "^12.0.1",
53
+ "@nestjs/testing": "^12.0.1",
54
54
  "reflect-metadata": "^0.2.2",
55
55
  "rxjs": "^7.8.1",
56
56
  "tsup": "^8.3.0",