nestjs-devtools 1.5.3 → 1.5.4
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/dist/toolbar/profiler.js
CHANGED
|
@@ -64,7 +64,15 @@ 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
|
-
|
|
67
|
+
#history-detail { display: none; margin-top: 12px; }
|
|
68
|
+
#history-detail.open { display: block; }
|
|
69
|
+
#history-body tr { cursor: pointer; }
|
|
70
|
+
#history-body tr:hover { background: #f0f7ff; }
|
|
71
|
+
#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
|
+
.query-table { width: 100%; }
|
|
68
76
|
.query-row { display: flex; align-items: flex-start; padding: 5px 0; gap: 6px; border-bottom: 1px solid #eee; font-size: 11px; }
|
|
69
77
|
.query-row:last-child { border-bottom: none; }
|
|
70
78
|
.query-num { color: #999; width: 22px; flex-shrink: 0; }
|
|
@@ -122,6 +130,9 @@ const PROFILER_PAGE = (config) => {
|
|
|
122
130
|
<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>
|
|
123
131
|
<tbody id="history-body"></tbody>
|
|
124
132
|
</table>
|
|
133
|
+
<div id="history-detail" class="panel">
|
|
134
|
+
<div id="history-detail-body" class="panel-body open" style="display:block;padding:16px"></div>
|
|
135
|
+
</div>
|
|
125
136
|
</div>
|
|
126
137
|
</div>
|
|
127
138
|
</div>
|
|
@@ -249,25 +260,75 @@ const PROFILER_PAGE = (config) => {
|
|
|
249
260
|
});
|
|
250
261
|
}
|
|
251
262
|
|
|
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>';
|
|
286
|
+
});
|
|
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;
|
|
293
|
+
}
|
|
294
|
+
|
|
252
295
|
function loadHistory() {
|
|
253
296
|
fetch(BASE + '/__devtools/history').then(function(r){return r.json()}).then(function(rows){
|
|
254
297
|
var tbody = document.getElementById('history-body');
|
|
298
|
+
var detail = document.getElementById('history-detail');
|
|
255
299
|
tbody.innerHTML = '';
|
|
256
300
|
if (!rows || rows.length===0) {
|
|
257
301
|
tbody.innerHTML = '<tr><td colspan="5" style="padding:20px;text-align:center;color:#bbb">No requests recorded yet</td></tr>';
|
|
258
302
|
return;
|
|
259
303
|
}
|
|
304
|
+
var selectedId = tbody.getAttribute('data-selected');
|
|
260
305
|
rows.forEach(function(r){
|
|
261
306
|
var sc = r.statusCode;
|
|
262
307
|
var scCls = sc>=400 ? 'error-text' : sc>=300 ? 'warn-text' : 'ok-text';
|
|
263
308
|
var mCls = 'badge-'+r.method.toLowerCase();
|
|
264
|
-
|
|
309
|
+
var sel = r.id===selectedId ? ' selected' : '';
|
|
310
|
+
var tr = document.createElement('tr');
|
|
311
|
+
tr.className = sel;
|
|
312
|
+
tr.innerHTML =
|
|
265
313
|
'<td style="padding:8px 12px;border-bottom:1px solid #eee;color:#888">'+escape(new Date(r.timestamp).toLocaleTimeString())+'</td>'+
|
|
266
314
|
'<td style="padding:8px 12px;border-bottom:1px solid #eee"><span class="badge '+mCls+'">'+escape(r.method)+'</span></td>'+
|
|
267
315
|
'<td style="padding:8px 12px;border-bottom:1px solid #eee;font-family:SF Mono,Menlo,monospace;font-size:11px">'+escape(r.path)+'</td>'+
|
|
268
316
|
'<td style="padding:8px 12px;border-bottom:1px solid #eee"><span class="'+scCls+'">'+sc+'</span></td>'+
|
|
269
|
-
'<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>'
|
|
270
|
-
|
|
317
|
+
'<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
|
+
});
|
|
331
|
+
tbody.appendChild(tr);
|
|
271
332
|
});
|
|
272
333
|
}).catch(function(e){
|
|
273
334
|
console.error('[Devtools] Failed to load history:', e);
|
|
@@ -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
|
|
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"}
|