nestjs-devtools 1.5.4 → 1.5.6

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.
@@ -48,8 +48,8 @@ let DevtoolsController = class DevtoolsController {
48
48
  res.send(this.devtoolsService.getHistorySummary());
49
49
  }
50
50
  getRequestDetail(id, res) {
51
- const history = this.devtoolsService.getHistory();
52
- res.send(history.find((r) => r.id === id) ?? null);
51
+ const panels = this.devtoolsService.getRequestPanels(id);
52
+ res.send(panels ?? null);
53
53
  }
54
54
  };
55
55
  exports.DevtoolsController = DevtoolsController;
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.controller.js","sourceRoot":"","sources":["../devtools.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA+E;AAC/E,yDAAqD;AAErD,6DAAwF;AACxF,iDAAuE;AAIhE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YACmB,eAAgC,EAGhC,aAAkC,EAAE,EAEpC,cAA0D;QAL1D,oBAAe,GAAf,eAAe,CAAiB;QAGhC,eAAU,GAAV,UAAU,CAA0B;QAEpC,mBAAc,GAAd,cAAc,CAA4C;IAC1E,CAAC;IAGJ,WAAW,CAAQ,GAAQ;QACzB,IAAI,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAAC,CAAC;QACjF,GAAG,CAAC,IAAI,CAAC,IAAA,wBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/C,CAAC;IAGD,cAAc,CAAQ,GAAQ;QAC5B,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;YACvF,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAGD,UAAU,CAAQ,GAAQ;QACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACrD,CAAC;IAGD,gBAAgB,CAAc,EAAU,EAAS,GAAQ;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC;QAClD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC;IACrD,CAAC;CACF,CAAA;AAvCY,gDAAkB;AAW7B;IADC,IAAA,YAAG,GAAE;IACO,WAAA,IAAA,YAAG,GAAE,CAAA;;;;qDAGjB;AAGD;IADC,IAAA,YAAG,EAAC,MAAM,CAAC;IACI,WAAA,IAAA,YAAG,GAAE,CAAA;;;;wDAUpB;AAGD;IADC,IAAA,YAAG,EAAC,SAAS,CAAC;IACH,WAAA,IAAA,YAAG,GAAE,CAAA;;;;oDAEhB;AAGD;IADC,IAAA,YAAG,EAAC,aAAa,CAAC;IACD,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IAAc,WAAA,IAAA,YAAG,GAAE,CAAA;;;;0DAG/C;6BAtCU,kBAAkB;IAD9B,IAAA,mBAAU,EAAC,YAAY,CAAC;IAIpB,WAAA,IAAA,iBAAQ,GAAE,CAAA;IACV,WAAA,IAAA,eAAM,EAAC,8CAAyB,CAAC,CAAA;IAEjC,WAAA,IAAA,eAAM,EAAC,0CAAqB,CAAC,CAAA;qCAJI,kCAAe;GAFxC,kBAAkB,CAuC9B"}
1
+ {"version":3,"file":"devtools.controller.js","sourceRoot":"","sources":["../devtools.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA+E;AAC/E,yDAAqD;AAErD,6DAAwF;AACxF,iDAAuE;AAIhE,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YACmB,eAAgC,EAGhC,aAAkC,EAAE,EAEpC,cAA0D;QAL1D,oBAAe,GAAf,eAAe,CAAiB;QAGhC,eAAU,GAAV,UAAU,CAA0B;QAEpC,mBAAc,GAAd,cAAc,CAA4C;IAC1E,CAAC;IAGJ,WAAW,CAAQ,GAAQ;QACzB,IAAI,CAAC;YAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAAC,CAAC;QACjF,GAAG,CAAC,IAAI,CAAC,IAAA,wBAAa,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/C,CAAC;IAGD,cAAc,CAAQ,GAAQ;QAC5B,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;YACvF,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAGD,UAAU,CAAQ,GAAQ;QACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACrD,CAAC;IAGD,gBAAgB,CAAc,EAAU,EAAS,GAAQ;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IAC3B,CAAC;CACF,CAAA;AAvCY,gDAAkB;AAW7B;IADC,IAAA,YAAG,GAAE;IACO,WAAA,IAAA,YAAG,GAAE,CAAA;;;;qDAGjB;AAGD;IADC,IAAA,YAAG,EAAC,MAAM,CAAC;IACI,WAAA,IAAA,YAAG,GAAE,CAAA;;;;wDAUpB;AAGD;IADC,IAAA,YAAG,EAAC,SAAS,CAAC;IACH,WAAA,IAAA,YAAG,GAAE,CAAA;;;;oDAEhB;AAGD;IADC,IAAA,YAAG,EAAC,aAAa,CAAC;IACD,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IAAc,WAAA,IAAA,YAAG,GAAE,CAAA;;;;0DAG/C;6BAtCU,kBAAkB;IAD9B,IAAA,mBAAU,EAAC,YAAY,CAAC;IAIpB,WAAA,IAAA,iBAAQ,GAAE,CAAA;IACV,WAAA,IAAA,eAAM,EAAC,8CAAyB,CAAC,CAAA;IAEjC,WAAA,IAAA,eAAM,EAAC,0CAAqB,CAAC,CAAA;qCAJI,kCAAe;GAFxC,kBAAkB,CAuC9B"}
@@ -1,4 +1,4 @@
1
- import { RequestDebugInfo } from './interfaces';
1
+ import { RequestDebugInfo, DevtoolsData } from './interfaces';
2
2
  export declare class DevtoolsService {
3
3
  private readonly history;
4
4
  private readonly maxHistory;
@@ -25,4 +25,5 @@ export declare class DevtoolsService {
25
25
  duration: number;
26
26
  timestamp: Date;
27
27
  }[];
28
+ getRequestPanels(id: string): Record<string, DevtoolsData> | null;
28
29
  }
@@ -73,6 +73,75 @@ let DevtoolsService = class DevtoolsService {
73
73
  timestamp: r.timestamp,
74
74
  }));
75
75
  }
76
+ getRequestPanels(id) {
77
+ const req = this.history.find((r) => r.id === id);
78
+ if (!req)
79
+ return null;
80
+ const panels = {};
81
+ panels.request = {
82
+ label: 'Request',
83
+ icon: '🌐',
84
+ summary: `${req.method} ${req.path} → ${req.statusCode}`,
85
+ details: {
86
+ method: req.method,
87
+ path: req.path,
88
+ status: req.statusCode,
89
+ duration: `${req.duration.toFixed(2)} ms`,
90
+ memory: `${(req.memory / 1024 / 1024).toFixed(2)} MB`,
91
+ timestamp: req.timestamp.toISOString(),
92
+ route: req.route,
93
+ },
94
+ };
95
+ panels.performance = {
96
+ label: 'Performance',
97
+ icon: '⚡',
98
+ summary: `${req.duration.toFixed(1)} ms, ${(req.memory / 1024 / 1024).toFixed(1)} MB`,
99
+ details: {
100
+ duration: `${req.duration.toFixed(2)} ms`,
101
+ peakMemory: `${(req.memory / 1024 / 1024).toFixed(2)} MB`,
102
+ queries: req.queries.length,
103
+ queryTime: `${req.queries.reduce((a, q) => a + q.duration, 0).toFixed(2)} ms`,
104
+ },
105
+ };
106
+ const totalQueryDuration = req.queries.reduce((a, q) => a + q.duration, 0);
107
+ panels.database = {
108
+ label: 'Database',
109
+ icon: '🗄️',
110
+ summary: `${req.queries.length} queries in ${totalQueryDuration.toFixed(1)} ms`,
111
+ details: {
112
+ totalQueries: req.queries.length,
113
+ totalTime: `${totalQueryDuration.toFixed(2)} ms`,
114
+ queries: req.queries.map((q) => ({
115
+ sql: q.sql,
116
+ duration: `${q.duration.toFixed(2)} ms`,
117
+ })),
118
+ },
119
+ };
120
+ const errors = req.logs.filter((l) => l.level === 'error');
121
+ const warnings = req.logs.filter((l) => l.level === 'warn');
122
+ const logsDetails = {
123
+ total: req.logs.length,
124
+ errors: errors.length,
125
+ warnings: warnings.length,
126
+ entries: req.logs.slice(-20).map((l) => ({
127
+ level: l.level,
128
+ message: l.message,
129
+ })),
130
+ };
131
+ if (req.exception) {
132
+ logsDetails.exception = {
133
+ message: req.exception.message,
134
+ stack: req.exception.stack,
135
+ };
136
+ }
137
+ panels.logs = {
138
+ label: 'Logs',
139
+ icon: '📝',
140
+ summary: `${req.logs.length} entries (${errors.length} errors, ${warnings.length} warnings)`,
141
+ details: logsDetails,
142
+ };
143
+ return panels;
144
+ }
76
145
  };
77
146
  exports.DevtoolsService = DevtoolsService;
78
147
  exports.DevtoolsService = DevtoolsService = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.service.js","sourceRoot":"","sources":["../devtools.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAIrC,IAAM,eAAe,GAArB,MAAM,eAAe;IAI1B,YAAY,UAAU,GAAG,EAAE;QAHV,YAAO,GAAuB,EAAE,CAAC;QAO1C,mBAAc,GAA4B,IAAI,CAAC;QAHrD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAID,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,iBAAiB,CAAC,IAAsB;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,GAAW,EAAE,QAAgB;QACpC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,KAAa;QACnC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,YAAY,CAAC,SAA6C;QACxD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACrB,CAAC;YACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAA;AA5EY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;;GACA,eAAe,CA4E3B"}
1
+ {"version":3,"file":"devtools.service.js","sourceRoot":"","sources":["../devtools.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAIrC,IAAM,eAAe,GAArB,MAAM,eAAe;IAI1B,YAAY,UAAU,GAAG,EAAE;QAHV,YAAO,GAAuB,EAAE,CAAC;QAO1C,mBAAc,GAA4B,IAAI,CAAC;QAHrD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAID,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,iBAAiB,CAAC,IAAsB;QACtC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,GAAW,EAAE,QAAgB;QACpC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe,EAAE,KAAa;QACnC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,YAAY,CAAC,SAA6C;QACxD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,SAAS,GAAG,SAAS,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACrB,CAAC;YACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;SACvB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,gBAAgB,CAAC,EAAU;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,MAAM,MAAM,GAAiC,EAAE,CAAC;QAEhD,MAAM,CAAC,OAAO,GAAG;YACf,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,UAAU,EAAE;YACxD,OAAO,EAAE;gBACP,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,UAAU;gBACtB,QAAQ,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;gBACzC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;gBACrD,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;gBACtC,KAAK,EAAE,GAAG,CAAC,KAAK;aACjB;SACF,CAAC;QAEF,MAAM,CAAC,WAAW,GAAG;YACnB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;YACrF,OAAO,EAAE;gBACP,QAAQ,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;gBACzC,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;gBACzD,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM;gBAC3B,SAAS,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;aAC9E;SACF,CAAC;QAEF,MAAM,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,QAAQ,GAAG;YAChB,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,eAAe,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;YAC/E,OAAO,EAAE;gBACP,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM;gBAChC,SAAS,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;gBAChD,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC/B,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,QAAQ,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;iBACxC,CAAC,CAAC;aACJ;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;QAC5D,MAAM,WAAW,GAA4B;YAC3C,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;YACtB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,QAAQ,CAAC,MAAM;YACzB,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvC,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC;SACJ,CAAC;QACF,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAClB,WAAW,CAAC,SAAS,GAAG;gBACtB,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO;gBAC9B,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK;aAC3B,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,IAAI,GAAG;YACZ,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,aAAa,MAAM,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,YAAY;YAC5F,OAAO,EAAE,WAAW;SACrB,CAAC;QAEF,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AAvJY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;;GACA,eAAe,CAuJ3B"}
@@ -64,14 +64,9 @@ const PROFILER_PAGE = (config) => {
64
64
  .panel-body tr:last-child td, .panel-body tr:last-child th { border-bottom: none; }
65
65
  .empty { color: #bbb; font-size: 12px; }
66
66
  .mono { font-family: SF Mono,Menlo,monospace; font-size: 11px; }
67
- #history-detail { display: none; margin-top: 12px; }
68
- #history-detail.open { display: block; }
69
67
  #history-body tr { cursor: pointer; }
70
68
  #history-body tr:hover { background: #f0f7ff; }
71
69
  #history-body tr.selected { background: #e1effa; }
72
- .detail-section { margin-bottom: 12px; }
73
- .detail-section:last-child { margin-bottom: 0; }
74
- .detail-section h4 { font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; color: #999; margin-bottom: 6px; }
75
70
  .query-table { width: 100%; }
76
71
  .query-row { display: flex; align-items: flex-start; padding: 5px 0; gap: 6px; border-bottom: 1px solid #eee; font-size: 11px; }
77
72
  .query-row:last-child { border-bottom: none; }
@@ -102,6 +97,37 @@ const PROFILER_PAGE = (config) => {
102
97
  .status-300 { background: #fff3cd; color: #856404; }
103
98
  .status-400 { background: #f8d7da; color: #721c24; }
104
99
  .status-500 { background: #f8d7da; color: #721c24; }
100
+ #history-body tr { cursor: pointer; }
101
+ #history-body tr:hover { background: #f0f7ff; }
102
+ #history-body tr.selected { background: #e1effa; }
103
+ .sf-detail { display: none; }
104
+ .sf-detail.open { display: flex; }
105
+ .sf-toolbar {
106
+ background: #1a1a1a; color: #ccc; display: flex; align-items: center;
107
+ height: 30px; padding: 0 10px; font-size: 11px;
108
+ box-shadow: 0 1px 4px rgba(0,0,0,0.3);
109
+ }
110
+ .sf-toolbar .back { color: #888; cursor: pointer; font-size: 11px; padding: 0 8px; text-decoration: none; }
111
+ .sf-toolbar .back:hover { color: #fff; }
112
+ .sf-toolbar .spacer { flex: 1; }
113
+ .sf-toolbar .req-summary { display: flex; align-items: center; gap: 8px; font-size: 11px; }
114
+ .sf-sidebar {
115
+ width: 200px; background: #fff; border-right: 1px solid #ddd;
116
+ flex-shrink: 0; font-size: 12px; overflow-y: auto;
117
+ }
118
+ .sf-sidebar .sf-metrics { padding: 12px; border-bottom: 1px solid #eee; }
119
+ .sf-sidebar .sf-metrics .m-row { display: flex; justify-content: space-between; padding: 2px 0; font-size: 11px; }
120
+ .sf-sidebar .sf-metrics .m-label { color: #999; }
121
+ .sf-sidebar .sf-metrics .m-value { color: #333; font-weight: 500; text-align: right; font-size: 11px; }
122
+ .sf-sidebar .panel-nav { list-style: none; padding: 0; margin: 0; }
123
+ .sf-sidebar .panel-nav li {
124
+ padding: 6px 12px; cursor: pointer; font-size: 11px; color: #555;
125
+ border-bottom: 1px solid #f0f0f0; display: flex; align-items: center; gap: 6px;
126
+ }
127
+ .sf-sidebar .panel-nav li:hover { background: #f5f9ff; color: #222; }
128
+ .sf-sidebar .panel-nav li.active { background: #e8f0fe; color: #1a73e8; font-weight: 600; border-right: 3px solid #1a73e8; }
129
+ .sf-main { flex: 1; padding: 16px; overflow-y: auto; }
130
+ .sf-main .panel { margin-bottom: 0; }
105
131
  </style>
106
132
  </head>
107
133
  <body>
@@ -130,9 +156,20 @@ const PROFILER_PAGE = (config) => {
130
156
  <thead><tr style="background:#fafafa"><th style="padding:8px 12px;text-align:left;color:#888;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.5px;border-bottom:1px solid #ddd">Time</th><th style="padding:8px 12px;text-align:left;color:#888;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.5px;border-bottom:1px solid #ddd">Method</th><th style="padding:8px 12px;text-align:left;color:#888;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.5px;border-bottom:1px solid #ddd">Path</th><th style="padding:8px 12px;text-align:left;color:#888;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.5px;border-bottom:1px solid #ddd">Status</th><th style="padding:8px 12px;text-align:left;color:#888;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.5px;border-bottom:1px solid #ddd">Duration</th></tr></thead>
131
157
  <tbody id="history-body"></tbody>
132
158
  </table>
133
- <div id="history-detail" class="panel">
134
- <div id="history-detail-body" class="panel-body open" style="display:block;padding:16px"></div>
159
+ </div>
160
+ </div>
161
+ <div id="tab-request" class="tab-content" style="display:none">
162
+ <div class="sf-toolbar">
163
+ <a class="back" id="back-to-history">&larr; Back to list</a>
164
+ <span class="spacer"></span>
165
+ <span class="req-summary" id="detail-toolbar-summary"></span>
166
+ </div>
167
+ <div class="layout" style="min-height:calc(100vh - 60px)">
168
+ <div class="sf-sidebar">
169
+ <div class="sf-metrics" id="detail-metrics"></div>
170
+ <ul class="panel-nav" id="detail-panel-nav"></ul>
135
171
  </div>
172
+ <div class="sf-main" id="detail-main"></div>
136
173
  </div>
137
174
  </div>
138
175
  </div>
@@ -147,12 +184,9 @@ const PROFILER_PAGE = (config) => {
147
184
 
148
185
  document.querySelectorAll('[data-tab]').forEach(function(el){
149
186
  el.addEventListener('click', function(){
150
- document.querySelectorAll('[data-tab]').forEach(function(b){b.classList.remove('active')});
151
- document.querySelectorAll('.tab-content').forEach(function(c){c.style.display='none'});
152
- el.classList.add('active');
153
- activeTab = el.getAttribute('data-tab');
154
- document.getElementById('tab-'+activeTab).style.display='';
155
- if (activeTab==='history') loadHistory();
187
+ var tab = el.getAttribute('data-tab');
188
+ switchTab(tab);
189
+ if (tab==='history') loadHistory();
156
190
  });
157
191
  });
158
192
 
@@ -260,74 +294,117 @@ const PROFILER_PAGE = (config) => {
260
294
  });
261
295
  }
262
296
 
263
- function renderRequestDetail(d) {
264
- if (!d) return '<span class="empty">No details available</span>';
265
- var h = '<div class="detail-section"><h4>Request</h4><table>'+
266
- '<tr><th style="width:80px">Method</th><td><span class="badge badge-'+d.method.toLowerCase()+'">'+escape(d.method)+'</span></td></tr>'+
267
- '<tr><th>Path</th><td class="mono">'+escape(d.path)+'</td></tr>'+
268
- '<tr><th>Status</th><td><span class="status-badge status-'+(d.statusCode||'')+'">'+escape(d.statusCode||'')+'</span></td></tr>'+
269
- '<tr><th>Duration</th><td>'+(d.duration!=null?d.duration.toFixed(1):'')+' ms</td></tr>'+
270
- '<tr><th>Memory</th><td>'+escape(d.memory||'')+'</td></tr>'+
271
- '<tr><th>Route</th><td class="mono" style="font-size:10px">'+escape(d.route||'')+'</td></tr>'+
272
- '<tr><th>Time</th><td>'+escape(new Date(d.timestamp).toLocaleTimeString())+'</td></tr>'+
273
- '</table></div>';
274
- if (d.queries && d.queries.length>0) {
275
- h += '<div class="detail-section"><h4>Queries ('+d.queries.length+')</h4>';
276
- d.queries.forEach(function(q,i){
277
- h += '<div class="query-row"><span class="query-num">'+(i+1)+'</span><span class="query-sql">'+escape(q.sql||'')+'</span><span class="query-time">'+escape(q.duration||'')+'</span></div>';
278
- });
279
- h += '</div>';
280
- }
281
- if (d.logs && d.logs.length>0) {
282
- h += '<div class="detail-section"><h4>Logs ('+d.logs.length+')</h4>';
283
- d.logs.forEach(function(e){
284
- var lc = e.level==='error' ? 'log-error' : e.level==='warn' ? 'log-warn' : 'log-info';
285
- h += '<div class="log-row"><span class="log-level '+lc+'">'+escape(e.level||'')+'</span><span>'+escape(e.message||'')+'</span></div>';
297
+ var panelOrder = ['request','performance','database','routes','logs'];
298
+ var currentPanels = {};
299
+ var currentPanelKey = '';
300
+
301
+ function showPanel(key) {
302
+ currentPanelKey = key;
303
+ var p = currentPanels[key];
304
+ if (!p) return;
305
+ document.querySelectorAll('#detail-panel-nav li').forEach(function(l){l.classList.remove('active')});
306
+ var navItem = document.getElementById('nav-'+key);
307
+ if (navItem) navItem.classList.add('active');
308
+ document.getElementById('detail-main').innerHTML =
309
+ '<div class="panel"><div class="panel-header" style="cursor:default"><span>'+escape(p.label)+'</span><span class="summary">'+escape(p.summary||'')+'</span></div><div class="panel-body open" style="display:block">'+renderPanelContent(p)+'</div></div>';
310
+ }
311
+
312
+ function showRequestDetail(id) {
313
+ fetch(BASE + '/__devtools/request/' + id).then(function(r){return r.json()}).then(function(panels){
314
+ if (!panels) { return; }
315
+ currentPanels = panels;
316
+
317
+ var first = null;
318
+ var firstKey = null;
319
+ var order = panelOrder;
320
+ for (var i=0;i<order.length;i++) {
321
+ var p = panels[order[i]];
322
+ if (p && p.label) { first = p; firstKey = order[i]; break; }
323
+ }
324
+ if (!first) {
325
+ for (var k in panels) { first = panels[k]; firstKey = k; break; }
326
+ }
327
+ if (!first || !first.details) { return; }
328
+ var dd = first.details;
329
+
330
+ document.getElementById('detail-toolbar-summary').innerHTML =
331
+ '<span class="badge badge-'+((dd.method||'get').toLowerCase())+'">'+escape(dd.method||'')+'</span>'+
332
+ ' <span class="mono" style="color:#ddd">'+escape(dd.path||'')+'</span>'+
333
+ ' <span class="status-badge status-'+(dd.status||'')+'">'+escape(dd.status||'')+'</span>'+
334
+ ' <span style="color:#999">'+escape(dd.duration||'')+'</span>'+
335
+ ' <span style="color:#999">'+escape(dd.memory||'')+'</span>';
336
+
337
+ var metricsHtml = '';
338
+ var metricFields = ['method','path','status','duration','memory','route'];
339
+ for (var i=0;i<metricFields.length;i++) {
340
+ var k = metricFields[i];
341
+ var v = dd[k];
342
+ if (v==null) continue;
343
+ if (k==='method') {
344
+ metricsHtml += '<div class="m-row"><span class="m-label">Method</span><span class="m-value"><span class="badge badge-'+v.toLowerCase()+'">'+escape(v)+'</span></span></div>';
345
+ } else if (k==='status') {
346
+ metricsHtml += '<div class="m-row"><span class="m-label">Status</span><span class="m-value"><span class="status-badge status-'+v+'">'+escape(v)+'</span></span></div>';
347
+ } else {
348
+ metricsHtml += '<div class="m-row"><span class="m-label">'+escape(k.charAt(0).toUpperCase()+k.slice(1))+'</span><span class="m-value '+(k==='path'||k==='route'?'mono':'')+'">'+escape(v)+'</span></div>';
349
+ }
350
+ }
351
+ document.getElementById('detail-metrics').innerHTML = metricsHtml;
352
+
353
+ var navHtml = '';
354
+ for (var i=0;i<order.length;i++) {
355
+ var p = panels[order[i]];
356
+ if (!p || !p.label) continue;
357
+ var active = order[i]===firstKey ? ' class="active"' : '';
358
+ navHtml += '<li id="nav-'+order[i]+'"'+active+' data-panel="'+order[i]+'">'+escape(p.icon||'')+' '+escape(p.label)+'</li>';
359
+ }
360
+ for (var k in panels) {
361
+ if (order.indexOf(k)!==-1) continue;
362
+ var p = panels[k];
363
+ if (!p || !p.label) continue;
364
+ navHtml += '<li id="nav-'+k+'" data-panel="'+k+'">'+escape(p.icon||'')+' '+escape(p.label)+'</li>';
365
+ }
366
+ document.getElementById('detail-panel-nav').innerHTML = navHtml;
367
+
368
+ document.querySelectorAll('#detail-panel-nav li').forEach(function(el){
369
+ el.addEventListener('click', function(){ showPanel(this.getAttribute('data-panel')); });
286
370
  });
287
- h += '</div>';
288
- }
289
- if (d.exception) {
290
- h += '<div class="detail-section"><h4>Exception</h4><div class="exception-box"><div class="msg">'+escape(d.exception.message||'')+'</div><div class="stack">'+escape(d.exception.stack||'')+'</div></div></div>';
291
- }
292
- return h;
371
+
372
+ switchTab('request');
373
+ showPanel(firstKey);
374
+ }).catch(function(e){
375
+ console.error('[Devtools] Failed to load request detail:', e);
376
+ });
377
+ }
378
+
379
+ function switchTab(tab) {
380
+ document.querySelectorAll('[data-tab]').forEach(function(b){b.classList.remove('active')});
381
+ document.querySelectorAll('.tab-content').forEach(function(c){c.style.display='none'});
382
+ activeTab = tab;
383
+ var tabBtn = document.querySelector('[data-tab="'+tab+'"]');
384
+ if (tabBtn) tabBtn.classList.add('active');
385
+ document.getElementById('tab-'+tab).style.display='';
293
386
  }
294
387
 
295
388
  function loadHistory() {
296
389
  fetch(BASE + '/__devtools/history').then(function(r){return r.json()}).then(function(rows){
297
390
  var tbody = document.getElementById('history-body');
298
- var detail = document.getElementById('history-detail');
299
391
  tbody.innerHTML = '';
300
392
  if (!rows || rows.length===0) {
301
393
  tbody.innerHTML = '<tr><td colspan="5" style="padding:20px;text-align:center;color:#bbb">No requests recorded yet</td></tr>';
302
394
  return;
303
395
  }
304
- var selectedId = tbody.getAttribute('data-selected');
305
396
  rows.forEach(function(r){
306
397
  var sc = r.statusCode;
307
398
  var scCls = sc>=400 ? 'error-text' : sc>=300 ? 'warn-text' : 'ok-text';
308
399
  var mCls = 'badge-'+r.method.toLowerCase();
309
- var sel = r.id===selectedId ? ' selected' : '';
310
400
  var tr = document.createElement('tr');
311
- tr.className = sel;
312
401
  tr.innerHTML =
313
402
  '<td style="padding:8px 12px;border-bottom:1px solid #eee;color:#888">'+escape(new Date(r.timestamp).toLocaleTimeString())+'</td>'+
314
403
  '<td style="padding:8px 12px;border-bottom:1px solid #eee"><span class="badge '+mCls+'">'+escape(r.method)+'</span></td>'+
315
404
  '<td style="padding:8px 12px;border-bottom:1px solid #eee;font-family:SF Mono,Menlo,monospace;font-size:11px">'+escape(r.path)+'</td>'+
316
405
  '<td style="padding:8px 12px;border-bottom:1px solid #eee"><span class="'+scCls+'">'+sc+'</span></td>'+
317
406
  '<td style="padding:8px 12px;border-bottom:1px solid #eee;color:#888;font-family:SF Mono,Menlo,monospace">'+(r.duration!=null?r.duration.toFixed(1):'')+' ms</td>';
318
- tr.addEventListener('click', function(){
319
- document.querySelectorAll('#history-body tr').forEach(function(t){t.classList.remove('selected')});
320
- tr.classList.add('selected');
321
- tbody.setAttribute('data-selected', r.id);
322
- fetch(BASE + '/__devtools/request/' + r.id).then(function(r2){return r2.json()}).then(function(detailData){
323
- document.getElementById('history-detail-body').innerHTML = renderRequestDetail(detailData);
324
- detail.classList.add('open');
325
- }).catch(function(e){
326
- console.error('[Devtools] Failed to load request detail:', e);
327
- document.getElementById('history-detail-body').innerHTML = '<span class="empty">Failed to load detail</span>';
328
- detail.classList.add('open');
329
- });
330
- });
407
+ tr.addEventListener('click', function(){ showRequestDetail(r.id); });
331
408
  tbody.appendChild(tr);
332
409
  });
333
410
  }).catch(function(e){
@@ -336,6 +413,8 @@ const PROFILER_PAGE = (config) => {
336
413
  });
337
414
  }
338
415
 
416
+ document.getElementById('back-to-history').addEventListener('click', function(){ switchTab('history'); loadHistory(); });
417
+
339
418
  loadDashboard();
340
419
  })();
341
420
  </script>
@@ -1 +1 @@
1
- {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../toolbar/profiler.ts"],"names":[],"mappings":";;;AAIO,MAAM,aAAa,GAAG,CAAC,MAAoC,EAAE,EAAE;IACpE,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IAExC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiVD,CAAC;AACT,CAAC,CAAC;AArVW,QAAA,aAAa,iBAqVxB"}
1
+ {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../toolbar/profiler.ts"],"names":[],"mappings":";;;AAIO,MAAM,aAAa,GAAG,CAAC,MAAoC,EAAE,EAAE;IACpE,MAAM,EAAE,KAAK,GAAG,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IAExC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgaD,CAAC;AACT,CAAC,CAAC;AApaW,QAAA,aAAa,iBAoaxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestjs-devtools",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "Symfony-style debug toolbar for NestJS applications",
5
5
  "keywords": [
6
6
  "nestjs",