nestjs-devtools 1.3.2 → 1.4.0
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 +129 -84
- package/dist/toolbar/profiler.js.map +1 -1
- package/dist/toolbar/template.js +77 -48
- package/dist/toolbar/template.js.map +1 -1
- package/package.json +1 -1
package/dist/toolbar/profiler.js
CHANGED
|
@@ -4,16 +4,24 @@ exports.PROFILER_PAGE = void 0;
|
|
|
4
4
|
const PROFILER_PAGE = (config) => {
|
|
5
5
|
const { theme = 'dark' } = config ?? {};
|
|
6
6
|
const dark = theme === 'dark';
|
|
7
|
-
const bg = dark ? '#
|
|
8
|
-
const fg = dark ? '#
|
|
9
|
-
const cardBg = dark ? '#
|
|
10
|
-
const borderClr = dark ? '#
|
|
11
|
-
const headerBg = dark ? '#
|
|
12
|
-
const dimText = dark ? '#
|
|
13
|
-
const dimmerText = dark ? '#
|
|
14
|
-
const accentText = dark ? '#
|
|
15
|
-
const
|
|
16
|
-
const
|
|
7
|
+
const bg = dark ? '#0f172a' : '#f8fafc';
|
|
8
|
+
const fg = dark ? '#e2e8f0' : '#1e293b';
|
|
9
|
+
const cardBg = dark ? '#1e293b' : '#ffffff';
|
|
10
|
+
const borderClr = dark ? '#334155' : '#e2e8f0';
|
|
11
|
+
const headerBg = dark ? '#0f172a' : '#ffffff';
|
|
12
|
+
const dimText = dark ? '#64748b' : '#94a3b8';
|
|
13
|
+
const dimmerText = dark ? '#475569' : '#cbd5e1';
|
|
14
|
+
const accentText = dark ? '#38bdf8' : '#0284c7';
|
|
15
|
+
const labelFg = dark ? '#f1f5f9' : '#0f172a';
|
|
16
|
+
const navBg = dark ? '#1e293b' : '#f1f5f9';
|
|
17
|
+
const navFg = dark ? '#94a3b8' : '#475569';
|
|
18
|
+
const I = {
|
|
19
|
+
req: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M5 8h6M8 5l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
20
|
+
perf: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 4v4l2.5 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
21
|
+
db: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><ellipse cx="8" cy="4.5" rx="5" ry="2" stroke="currentColor" stroke-width="1.5"/><path d="M3 4.5v7c0 1.1 2.2 2 5 2s5-.9 5-2v-7" stroke="currentColor" stroke-width="1.5"/><path d="M3 8c0 1.1 2.2 2 5 2s5-.9 5-2" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
22
|
+
routes: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
23
|
+
log: '<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="2" width="12" height="12" rx="2" stroke="currentColor" stroke-width="1.5"/><path d="M5 6h6M5 9h4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
24
|
+
};
|
|
17
25
|
return `<!DOCTYPE html>
|
|
18
26
|
<html lang="en">
|
|
19
27
|
<head>
|
|
@@ -23,69 +31,93 @@ const PROFILER_PAGE = (config) => {
|
|
|
23
31
|
<style>
|
|
24
32
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
25
33
|
body {
|
|
26
|
-
font-family: -apple-system,
|
|
27
|
-
background: ${bg}; color: ${fg}; font-size: 13px; line-height: 1.
|
|
34
|
+
font-family: Inter,SF Pro,system-ui,-apple-system,sans-serif;
|
|
35
|
+
background: ${bg}; color: ${fg}; font-size: 13px; line-height: 1.6;
|
|
28
36
|
min-height: 100vh;
|
|
29
37
|
}
|
|
30
38
|
.header {
|
|
31
|
-
background: ${headerBg}; border-bottom:
|
|
32
|
-
padding: 16px
|
|
39
|
+
background: ${headerBg}; border-bottom: 1px solid ${borderClr};
|
|
40
|
+
padding: 16px 28px; display: flex; align-items: center; gap: 14px;
|
|
41
|
+
position: sticky; top: 0; z-index: 10;
|
|
33
42
|
}
|
|
34
|
-
.header h1 { font-size:
|
|
43
|
+
.header h1 { font-size: 17px; font-weight: 700; color: ${accentText}; letter-spacing: -0.3px; }
|
|
35
44
|
.header span { color: ${dimText}; font-size: 13px; }
|
|
36
|
-
.container { max-width: 1200px; margin: 0 auto; padding: 24px; }
|
|
37
|
-
.
|
|
45
|
+
.container { max-width: 1200px; margin: 0 auto; padding: 24px 28px; }
|
|
46
|
+
.nav { display: flex; gap: 4px; margin-bottom: 24px; background: ${navBg}; border-radius: 8px; padding: 3px; display: inline-flex; }
|
|
47
|
+
.nav button {
|
|
48
|
+
padding: 7px 16px; border-radius: 6px; border: none;
|
|
49
|
+
background: transparent; color: ${navFg}; cursor: pointer;
|
|
50
|
+
font-size: 13px; font-weight: 500; transition: all .12s ease;
|
|
51
|
+
}
|
|
52
|
+
.nav button.active { background: ${cardBg}; color: ${labelFg}; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
53
|
+
.nav button:hover:not(.active) { color: ${labelFg}; }
|
|
54
|
+
.section { display: none; }
|
|
55
|
+
.section.active { display: block; }
|
|
56
|
+
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; }
|
|
38
57
|
.card {
|
|
39
58
|
background: ${cardBg}; border-radius: 8px; border: 1px solid ${borderClr};
|
|
40
|
-
overflow: hidden; cursor: pointer; transition: border-color .15s;
|
|
59
|
+
overflow: hidden; cursor: pointer; transition: border-color .15s ease;
|
|
41
60
|
}
|
|
42
|
-
.card:hover { border-color:
|
|
61
|
+
.card:hover { border-color: ${accentText}; }
|
|
43
62
|
.card-header {
|
|
44
|
-
padding: 12px
|
|
45
|
-
|
|
63
|
+
padding: 12px 14px; display: flex; align-items: center; gap: 9px;
|
|
64
|
+
user-select: none;
|
|
46
65
|
}
|
|
47
|
-
.card-header .icon {
|
|
48
|
-
.card-header .label { font-weight: 600; font-size: 13px; }
|
|
66
|
+
.card-header .icon { color: ${accentText}; width: 16px; height: 16px; flex-shrink: 0; }
|
|
67
|
+
.card-header .label { font-weight: 600; font-size: 13px; color: ${labelFg}; }
|
|
49
68
|
.card-header .summary { color: ${dimText}; font-size: 11px; margin-left: auto; }
|
|
50
|
-
.card-body {
|
|
51
|
-
.card-body.open { max-height: 2000px;
|
|
69
|
+
.card-body { max-height: 0; overflow: hidden; transition: max-height .25s ease; }
|
|
70
|
+
.card-body.open { max-height: 2000px; }
|
|
71
|
+
.card-body-inner { padding: 0 14px 14px; }
|
|
52
72
|
.card-body table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
53
73
|
.card-body td, .card-body th {
|
|
54
74
|
padding: 6px 8px; border-bottom: 1px solid ${borderClr}; text-align: left;
|
|
55
75
|
vertical-align: top; word-break: break-word;
|
|
56
76
|
}
|
|
57
|
-
.card-body th { color: ${dimText}; font-weight:
|
|
77
|
+
.card-body th { color: ${dimText}; font-weight: 500; width: 100px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; }
|
|
78
|
+
.card-body tr:last-child td, .card-body tr:last-child th { border-bottom: none; }
|
|
58
79
|
.badge {
|
|
59
|
-
display: inline-block; padding: 2px
|
|
60
|
-
font-size:
|
|
61
|
-
}
|
|
62
|
-
.badge-get { background: #065f46; color: #6ee7b7; }
|
|
63
|
-
.badge-post { background: #1e3a5f; color: #93c5fd; }
|
|
64
|
-
.badge-put { background: #713f12; color: #fcd34d; }
|
|
65
|
-
.badge-delete { background: #7f1d1d; color: #fca5a5; }
|
|
66
|
-
.badge-patch { background: #581c87; color: #d8b4fe; }
|
|
67
|
-
.empty { padding: 24px; text-align: center; color: ${dimmerText}; }
|
|
68
|
-
.mono { font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace; font-size: 11px; }
|
|
69
|
-
.history-table { width: 100%; border-collapse: collapse; margin-top: 16px; }
|
|
70
|
-
.history-table th { padding: 8px 12px; text-align: left; color: ${dimText}; font-weight: 600; border-bottom: 2px solid ${borderClr}; }
|
|
71
|
-
.history-table td { padding: 8px 12px; border-bottom: 1px solid ${borderClr}; }
|
|
72
|
-
.history-table tr:hover td { background: ${cardBg}; }
|
|
73
|
-
.error-text { color: #ef4444; }
|
|
74
|
-
.warn-text { color: #f59e0b; }
|
|
75
|
-
.ok-text { color: #10b981; }
|
|
76
|
-
.nav { display: flex; gap: 8px; margin-bottom: 24px; }
|
|
77
|
-
.nav button {
|
|
78
|
-
padding: 8px 16px; border-radius: 6px; border: 1px solid ${borderClr};
|
|
79
|
-
background: ${navBg}; color: ${navFg}; cursor: pointer; font-size: 13px;
|
|
80
|
+
display: inline-block; padding: 2px 7px; border-radius: 4px;
|
|
81
|
+
font-size: 10px; font-weight: 600; letter-spacing: 0.2px;
|
|
80
82
|
}
|
|
81
|
-
.
|
|
82
|
-
.
|
|
83
|
-
.
|
|
84
|
-
.
|
|
85
|
-
.
|
|
86
|
-
.
|
|
87
|
-
.
|
|
88
|
-
.
|
|
83
|
+
.badge-get { background: #065f4630; color: #34d399; }
|
|
84
|
+
.badge-post { background: #1e3a5f30; color: #93c5fd; }
|
|
85
|
+
.badge-put { background: #713f1230; color: #fcd34d; }
|
|
86
|
+
.badge-delete { background: #7f1d1d30; color: #fca5a5; }
|
|
87
|
+
.badge-patch { background: #581c8730; color: #d8b4fe; }
|
|
88
|
+
.badge-request { background: #0c4a6e30; color: #7dd3fc; }
|
|
89
|
+
.empty { padding: 20px; text-align: center; color: ${dimmerText}; font-size: 13px; }
|
|
90
|
+
.mono { font-family: ui-monospace,SF Mono,Menlo,monospace; font-size: 11px; }
|
|
91
|
+
.history-wrap { background: ${cardBg}; border: 1px solid ${borderClr}; border-radius: 8px; overflow: hidden; }
|
|
92
|
+
.history-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
93
|
+
.history-table th { padding: 10px 14px; text-align: left; color: ${dimText}; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; border-bottom: 1px solid ${borderClr}; background: ${dark ? '#0f172a' : '#f8fafc'}; }
|
|
94
|
+
.history-table td { padding: 10px 14px; border-bottom: 1px solid ${borderClr}; }
|
|
95
|
+
.history-table tr:last-child td { border-bottom: none; }
|
|
96
|
+
.history-table tr:hover td { background: ${dark ? '#33415520' : '#f1f5f9'}; }
|
|
97
|
+
.error-text { color: #f87171; font-weight: 600; }
|
|
98
|
+
.warn-text { color: #fbbf24; font-weight: 600; }
|
|
99
|
+
.ok-text { color: #34d399; font-weight: 600; }
|
|
100
|
+
.qlabel { display: inline-block; width: 18px; height: 18px; line-height: 18px; text-align: center; border-radius: 3px; font-size: 10px; font-weight: 700; margin-right: 6px; color: #fff; flex-shrink: 0; }
|
|
101
|
+
.qlabel-1 { background: #3b82f6; }
|
|
102
|
+
.qlabel-2 { background: #8b5cf6; }
|
|
103
|
+
.qlabel-3 { background: #10b981; }
|
|
104
|
+
.query-row { display: flex; align-items: flex-start; padding: 6px 0; gap: 6px; border-bottom: 1px solid ${borderClr}; }
|
|
105
|
+
.query-row:last-child { border-bottom: none; }
|
|
106
|
+
.query-sql { flex: 1; min-width: 0; }
|
|
107
|
+
.query-time { color: ${dark ? '#fbbf24' : '#b45309'}; white-space: nowrap; font-family: ui-monospace,SF Mono,monospace; font-size: 11px; }
|
|
108
|
+
.log-row { padding: 5px 0; border-bottom: 1px solid ${borderClr}; display: flex; align-items: flex-start; gap: 8px; }
|
|
109
|
+
.log-row:last-child { border-bottom: none; }
|
|
110
|
+
.log-level { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.3px; white-space: nowrap; }
|
|
111
|
+
.route-group { padding: 6px 0; }
|
|
112
|
+
.route-group-header { color: ${accentText}; font-weight: 600; font-size: 11px; padding: 4px 0; }
|
|
113
|
+
.route-item { padding: 2px 0 2px 14px; font-family: ui-monospace,SF Mono,monospace; font-size: 11px; }
|
|
114
|
+
.route-controller { color: ${dimText}; }
|
|
115
|
+
.exception-box { background: ${dark ? 'rgba(239,68,68,0.08)' : 'rgba(239,68,68,0.04)'}; border-radius: 6px; padding: 10px; }
|
|
116
|
+
.exception-box .msg { color: #f87171; font-weight: 600; font-size: 12px; margin-bottom: 6px; }
|
|
117
|
+
.exception-box .stack { font-family: ui-monospace,SF Mono,monospace; font-size: 11px; color: ${dimText}; white-space: pre-wrap; line-height: 1.4; }
|
|
118
|
+
.field-row { display: flex; padding: 4px 0; }
|
|
119
|
+
.field-label { color: ${dimText}; width: 100px; flex-shrink: 0; font-size: 11px; }
|
|
120
|
+
.field-value { color: ${labelFg}; word-break: break-all; }
|
|
89
121
|
</style>
|
|
90
122
|
</head>
|
|
91
123
|
<body>
|
|
@@ -102,15 +134,19 @@ const PROFILER_PAGE = (config) => {
|
|
|
102
134
|
<div class="grid" id="panel-grid"></div>
|
|
103
135
|
</div>
|
|
104
136
|
<div id="tab-history" class="section">
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
137
|
+
<div class="history-wrap">
|
|
138
|
+
<table class="history-table">
|
|
139
|
+
<thead><tr><th>Time</th><th>Method</th><th>Path</th><th>Status</th><th>Duration</th></tr></thead>
|
|
140
|
+
<tbody id="history-body"></tbody>
|
|
141
|
+
</table>
|
|
142
|
+
</div>
|
|
109
143
|
</div>
|
|
110
144
|
</div>
|
|
111
145
|
<script>
|
|
112
146
|
(function() {
|
|
113
147
|
var BASE = window.location.pathname.replace(/\\/__devtools\\/?$/, '');
|
|
148
|
+
var icons = ${JSON.stringify(I)};
|
|
149
|
+
|
|
114
150
|
function escape(s) { return s==null?'':String(s).replace(/[&<>"]/g,function(m){return {'&':'&','<':'<','>':'>','"':'"'}[m]}); }
|
|
115
151
|
|
|
116
152
|
document.querySelectorAll('[data-tab]').forEach(function(btn){
|
|
@@ -130,51 +166,44 @@ const PROFILER_PAGE = (config) => {
|
|
|
130
166
|
for (var k in d) {
|
|
131
167
|
var v = d[k];
|
|
132
168
|
if (k === 'queries' && Array.isArray(v)) {
|
|
169
|
+
if (v.length === 0) { h += '<tr><td colspan="2" style="padding:8px 0;color:${dimText}">No queries</td></tr>'; continue; }
|
|
133
170
|
h += '<tr><th>Queries</th><td>';
|
|
134
171
|
v.forEach(function(q,i){
|
|
135
172
|
var cls = 'qlabel-'+((i%3)+1);
|
|
136
|
-
h += '<div
|
|
137
|
-
h += '<span class="qlabel '+cls+'">#'+(i+1)+'</span>';
|
|
138
|
-
h += '<span class="mono">'+escape(q.sql||'')+'</span>';
|
|
139
|
-
h += '<span style="float:right;color:#fbbf24">'+escape(q.duration||'')+'</span>';
|
|
140
|
-
h += '</div>';
|
|
173
|
+
h += '<div class="query-row"><span class="qlabel '+cls+'">'+(i+1)+'</span><span class="query-sql mono">'+escape(q.sql||'')+'</span><span class="query-time">'+escape(q.duration||'')+'</span></div>';
|
|
141
174
|
});
|
|
142
175
|
h += '</td></tr>';
|
|
143
176
|
continue;
|
|
144
177
|
}
|
|
145
178
|
if (k === 'entries' && Array.isArray(v)) {
|
|
179
|
+
if (v.length === 0) { h += '<tr><td colspan="2" style="padding:8px 0;color:${dimText}">No entries</td></tr>'; continue; }
|
|
146
180
|
h += '<tr><th>Logs</th><td>';
|
|
147
181
|
v.forEach(function(e){
|
|
148
182
|
var lc = e.level==='error' ? 'error-text' : e.level==='warn' ? 'warn-text' : '';
|
|
149
|
-
h += '<div
|
|
150
|
-
h += '<span class="badge '+lc+'" style="background:#1f2937;text-transform:uppercase;font-size:10px;margin-right:6px">'+escape(e.level||'')+'</span>';
|
|
151
|
-
h += '<span>'+escape(e.message||'')+'</span>';
|
|
152
|
-
h += '</div>';
|
|
183
|
+
h += '<div class="log-row"><span class="log-level" style="color:'+lc+'">'+escape(e.level||'')+'</span><span>'+escape(e.message||'')+'</span></div>';
|
|
153
184
|
});
|
|
154
185
|
h += '</td></tr>';
|
|
155
186
|
continue;
|
|
156
187
|
}
|
|
157
188
|
if (k === 'grouped' && Array.isArray(v)) {
|
|
189
|
+
if (v.length === 0) { h += '<tr><td colspan="2" style="padding:8px 0;color:${dimText}">No routes</td></tr>'; continue; }
|
|
158
190
|
h += '<tr><th>Routes</th><td>';
|
|
159
191
|
v.forEach(function(g){
|
|
160
|
-
h += '<div
|
|
192
|
+
h += '<div class="route-group"><div class="route-group-header">'+escape(g.method||'')+' <span style="color:${dimText};font-weight:400">('+(g.count||0)+')</span></div>';
|
|
161
193
|
if (g.routes) g.routes.forEach(function(r){
|
|
162
|
-
h += '<div
|
|
163
|
-
h += escape(r.path||'')+' <span style="color:#6b7280">('+escape(r.controller||'')+')</span></div>';
|
|
194
|
+
h += '<div class="route-item">'+escape(r.path||'')+' <span class="route-controller">('+escape(r.controller||'')+')</span></div>';
|
|
164
195
|
});
|
|
196
|
+
h += '</div>';
|
|
165
197
|
});
|
|
166
198
|
h += '</td></tr>';
|
|
167
199
|
continue;
|
|
168
200
|
}
|
|
169
201
|
if (k === 'exception' && v && typeof v === 'object') {
|
|
170
|
-
h += '<tr><
|
|
171
|
-
h += '<div class="error-text" style="font-weight:600">'+escape(v.message||'')+'</div>';
|
|
172
|
-
h += '<pre class="mono" style="margin-top:6px;color:#9ca3af;white-space:pre-wrap">'+escape(v.stack||'')+'</pre>';
|
|
173
|
-
h += '</td></tr>';
|
|
202
|
+
h += '<tr><td colspan="2"><div class="exception-box"><div class="msg">'+escape(v.message||'')+'</div><div class="stack">'+escape(v.stack||'')+'</div></div></td></tr>';
|
|
174
203
|
continue;
|
|
175
204
|
}
|
|
176
205
|
if (k === 'stack') continue;
|
|
177
|
-
h += '<tr><th>'+escape(k)+'</th><td>'+escape(typeof v==='object'?JSON.stringify(v):v)+'</td></tr>';
|
|
206
|
+
h += '<tr><th>'+escape(k)+'</th><td class="mono">'+escape(typeof v==='object'?JSON.stringify(v):v)+'</td></tr>';
|
|
178
207
|
}
|
|
179
208
|
h += '</table>';
|
|
180
209
|
return h;
|
|
@@ -184,23 +213,39 @@ const PROFILER_PAGE = (config) => {
|
|
|
184
213
|
fetch(BASE + '/__devtools/data').then(function(r){return r.json()}).then(function(d){
|
|
185
214
|
var grid = document.getElementById('panel-grid');
|
|
186
215
|
grid.innerHTML = '';
|
|
187
|
-
var
|
|
188
|
-
|
|
216
|
+
var iconMap = {request:icons.req,performance:icons.perf,database:icons.db,routes:icons.routes,logs:icons.log};
|
|
217
|
+
var order = ['request','performance','database','routes','logs'];
|
|
218
|
+
order.forEach(function(key){
|
|
189
219
|
var p = d[key];
|
|
190
220
|
if (!p || !p.label) return;
|
|
191
221
|
var card = document.createElement('div');
|
|
192
222
|
card.className = 'card';
|
|
223
|
+
var icon = iconMap[key]||icons.log;
|
|
224
|
+
var bodyHtml = renderDetails(p);
|
|
193
225
|
card.innerHTML =
|
|
194
|
-
'<div class="card-header"><span class="icon">'+(
|
|
195
|
-
'<
|
|
196
|
-
'<span class="summary">'+escape(p.summary||'')+'</span></div>'+
|
|
197
|
-
'<div class="card-body">'+renderDetails(p)+'</div>';
|
|
226
|
+
'<div class="card-header"><span class="icon">'+icon+'</span><span class="label">'+escape(p.label)+'</span><span class="summary">'+escape(p.summary||'')+'</span></div>'+
|
|
227
|
+
'<div class="card-body"><div class="card-body-inner">'+bodyHtml+'</div></div>';
|
|
198
228
|
card.querySelector('.card-header').addEventListener('click', function(){
|
|
199
229
|
var body = card.querySelector('.card-body');
|
|
200
230
|
body.classList.toggle('open');
|
|
201
231
|
});
|
|
202
232
|
grid.appendChild(card);
|
|
203
233
|
});
|
|
234
|
+
for (var key in d) {
|
|
235
|
+
if (order.indexOf(key) !== -1) continue;
|
|
236
|
+
var p = d[key];
|
|
237
|
+
if (!p || !p.label) continue;
|
|
238
|
+
var card = document.createElement('div');
|
|
239
|
+
card.className = 'card';
|
|
240
|
+
card.innerHTML =
|
|
241
|
+
'<div class="card-header"><span class="icon">'+icons.log+'</span><span class="label">'+escape(p.label)+'</span><span class="summary">'+escape(p.summary||'')+'</span></div>'+
|
|
242
|
+
'<div class="card-body"><div class="card-body-inner">'+renderDetails(p)+'</div></div>';
|
|
243
|
+
card.querySelector('.card-header').addEventListener('click', function(){
|
|
244
|
+
var body = card.querySelector('.card-body');
|
|
245
|
+
body.classList.toggle('open');
|
|
246
|
+
});
|
|
247
|
+
grid.appendChild(card);
|
|
248
|
+
}
|
|
204
249
|
}).catch(function(){
|
|
205
250
|
document.getElementById('panel-grid').innerHTML = '<div class="empty">Failed to load profiler data. Make sure the server is running.</div>';
|
|
206
251
|
});
|
|
@@ -218,11 +263,11 @@ const PROFILER_PAGE = (config) => {
|
|
|
218
263
|
var statusClass = r.statusCode >= 400 ? 'error-text' : r.statusCode >= 300 ? 'warn-text' : 'ok-text';
|
|
219
264
|
var methodBadge = 'badge-'+r.method.toLowerCase();
|
|
220
265
|
tbody.innerHTML += '<tr>'+
|
|
221
|
-
'<td>'+escape(new Date(r.timestamp).toLocaleTimeString())+'</td>'+
|
|
266
|
+
'<td style="color:${dimText}">'+escape(new Date(r.timestamp).toLocaleTimeString())+'</td>'+
|
|
222
267
|
'<td><span class="badge '+methodBadge+'">'+escape(r.method)+'</span></td>'+
|
|
223
268
|
'<td class="mono">'+escape(r.path)+'</td>'+
|
|
224
269
|
'<td><span class="'+statusClass+'">'+r.statusCode+'</span></td>'+
|
|
225
|
-
'<td>'+r.duration.toFixed(1)+' ms</td>'+
|
|
270
|
+
'<td class="mono" style="color:${dimText}">'+(r.duration!=null?r.duration.toFixed(1):'')+' ms</td>'+
|
|
226
271
|
'</tr>';
|
|
227
272
|
});
|
|
228
273
|
}).catch(function(){
|
|
@@ -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;IACxC,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,CAAC;IAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACxC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3C,OAAO;;;;;;;;;;kBAUS,EAAE,YAAY,EAAE;;;;kBAIhB,QAAQ
|
|
1
|
+
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../toolbar/profiler.ts"],"names":[],"mappings":"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"}
|
package/dist/toolbar/template.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TOOLBAR_TEMPLATE = void 0;
|
|
4
|
+
const I = {
|
|
5
|
+
req: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M5 8h6M8 5l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
6
|
+
perf: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 4v4l2.5 1.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
7
|
+
db: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><ellipse cx="8" cy="4.5" rx="5" ry="2" stroke="currentColor" stroke-width="1.5"/><path d="M3 4.5v7c0 1.1 2.2 2 5 2s5-.9 5-2v-7" stroke="currentColor" stroke-width="1.5"/><path d="M3 8c0 1.1 2.2 2 5 2s5-.9 5-2" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
8
|
+
routes: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
9
|
+
log: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><rect x="2" y="2" width="12" height="12" rx="2" stroke="currentColor" stroke-width="1.5"/><path d="M5 6h6M5 9h4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
|
|
10
|
+
close: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
|
|
11
|
+
profiler: '<svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M2 3h12M2 8h12M2 13h8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><circle cx="12" cy="12" r="2.5" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
12
|
+
chevron: '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
13
|
+
};
|
|
4
14
|
const TOOLBAR_TEMPLATE = (config) => {
|
|
5
15
|
const { position = 'bottom-left', theme = 'dark' } = config ?? {};
|
|
6
16
|
const id = '__nestDevtools';
|
|
@@ -9,21 +19,23 @@ const TOOLBAR_TEMPLATE = (config) => {
|
|
|
9
19
|
const isRight = position.endsWith('right');
|
|
10
20
|
const outerPos = isTop ? 'top:0' : 'bottom:0';
|
|
11
21
|
const outerSide = isRight ? 'right:0' : 'left:0';
|
|
12
|
-
const outerBorder = isTop ? 'border-bottom:
|
|
22
|
+
const outerBorder = isTop ? 'border-bottom:1px solid' : 'border-top:1px solid';
|
|
13
23
|
const outerShadow = isTop
|
|
14
|
-
? 'box-shadow:0 4px
|
|
15
|
-
: 'box-shadow:0 -4px
|
|
24
|
+
? 'box-shadow:0 4px 24px rgba(0,0,0,0.3)'
|
|
25
|
+
: 'box-shadow:0 -4px 24px rgba(0,0,0,0.3)';
|
|
16
26
|
const dark = theme === 'dark';
|
|
17
|
-
const bg = dark ? '#
|
|
18
|
-
const fg = dark ? '#
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
+
const bg = dark ? '#0f172a' : '#fafbfc';
|
|
28
|
+
const fg = dark ? '#e2e8f0' : '#1e293b';
|
|
29
|
+
const accent = dark ? '#38bdf8' : '#0284c7';
|
|
30
|
+
const accentBg = dark ? '#0c4a6e30' : '#e0f2fe';
|
|
31
|
+
const panelBg = dark ? '#1e293b' : '#ffffff';
|
|
32
|
+
const borderClr = dark ? '#1e293b' : '#e2e8f0';
|
|
33
|
+
const panelBorder = dark ? '#334155' : '#e2e8f0';
|
|
34
|
+
const btnFg = dark ? '#94a3b8' : '#475569';
|
|
35
|
+
const btnBg = dark ? '#1e293b' : '#f1f5f9';
|
|
36
|
+
const btnHover = dark ? '#334155' : '#e2e8f0';
|
|
37
|
+
const dimText = dark ? '#64748b' : '#94a3b8';
|
|
38
|
+
const labelFg = dark ? '#f1f5f9' : '#0f172a';
|
|
27
39
|
const warnClr = '#f59e0b';
|
|
28
40
|
const errClr = '#ef4444';
|
|
29
41
|
const sqlTimeClr = dark ? '#fbbf24' : '#b45309';
|
|
@@ -32,90 +44,107 @@ const TOOLBAR_TEMPLATE = (config) => {
|
|
|
32
44
|
var D=document, B=D.body, C='__nestDt'+'${uid}';
|
|
33
45
|
var p = window.location.pathname.replace(\/[^\/]*$/,'') + '/__devtools';
|
|
34
46
|
var c=D.createElement('div'); c.id=C;
|
|
35
|
-
c.innerHTML='<div style="position:fixed;${outerPos};${outerSide};z-index:99999;font-family:system-ui,
|
|
47
|
+
c.innerHTML='<div style="position:fixed;${outerPos};${outerSide};z-index:99999;font-family:Inter,SF Pro,system-ui,-apple-system,sans-serif;font-size:12px;background:${bg};color:${fg};${outerBorder}:${borderClr};width:100%;${outerShadow}"><div style="display:flex;align-items:center;height:36px;padding:0 4px 0 10px;gap:2px;overflow-x:auto;white-space:nowrap;scrollbar-width:none"><span style="font-weight:700;font-size:13px;color:${accent};letter-spacing:-0.3px;padding-right:8px;flex-shrink:0">ND</span><div id="'+C+'-bar" style="display:flex;align-items:center;gap:2px;flex:1"></div><a href="'+p+'" target="_blank" style="display:inline-flex;align-items:center;gap:4px;color:${dimText};text-decoration:none;padding:4px 8px;font-size:11px;flex-shrink:0" title="Open profiler">${I.profiler}<span>Profiler</span></a><span id="'+C+'-toggle" style="display:inline-flex;align-items:center;color:${dimText};cursor:pointer;padding:4px 6px;font-size:10px;flex-shrink:0">${I.chevron}</span></div><div id="'+C+'-panel" style="display:none;border-top:1px solid ${panelBorder};background:${panelBg};font-size:12px;line-height:1.5;max-height:400px;overflow:hidden"></div></div>';
|
|
36
48
|
B.appendChild(c);
|
|
37
49
|
|
|
38
50
|
var lastActive=null;
|
|
39
51
|
function renderPanel(name, detail) {
|
|
40
|
-
var
|
|
41
|
-
if (lastActive===name) {
|
|
52
|
+
var pnl=D.getElementById(C+'-panel');
|
|
53
|
+
if (lastActive===name) { pnl.style.display='none'; lastActive=null; return; }
|
|
42
54
|
lastActive=name;
|
|
43
|
-
var h='<div style="
|
|
44
|
-
h+='<
|
|
45
|
-
h+='<span style="
|
|
46
|
-
h+='<span style="color:${dimText};
|
|
47
|
-
h+='<span style="margin-left:auto;cursor:pointer;color:${dimmerText};font-size:16px" onclick="document.getElementById('+C+'-panel).style.display=\\'none\\';lastActive=null">\u00d7</span>';
|
|
55
|
+
var h='<div style="display:flex;align-items:center;gap:8px;padding:10px 14px;border-bottom:1px solid ${panelBorder}">';
|
|
56
|
+
h+='<span style="font-weight:600;font-size:13px;color:${labelFg}">'+escapeHtml(detail.label)+'</span>';
|
|
57
|
+
h+='<span style="color:${dimText};font-size:11px">'+escapeHtml(detail.summary)+'</span>';
|
|
58
|
+
h+='<span style="margin-left:auto;cursor:pointer;color:${dimText};display:inline-flex;padding:2px" onclick="document.getElementById('+C+'-panel).style.display=\\'none\\';lastActive=null">${I.close}</span>';
|
|
48
59
|
h+='</div>';
|
|
49
|
-
h+='<
|
|
60
|
+
h+='<div style="padding:8px 14px 14px;overflow-y:auto;max-height:340px">';
|
|
61
|
+
h+='<table style="width:100%;border-collapse:collapse;font-size:12px">';
|
|
50
62
|
for (var k in detail.details) {
|
|
51
63
|
var v=detail.details[k];
|
|
52
64
|
if (k==='queries' && Array.isArray(v)) {
|
|
65
|
+
if (v.length===0) { h+='<tr><td style="padding:8px;color:${dimText}">No queries recorded</td></tr>'; continue; }
|
|
53
66
|
for (var i=0;i<v.length;i++) {
|
|
54
|
-
h+='<tr><td style="padding:
|
|
67
|
+
h+='<tr><td style="padding:5px 8px;color:${dimText};vertical-align:top;width:28px;font-size:11px;font-weight:500">'+(i+1)+'</td><td style="padding:5px 8px;font-family:ui-monospace,SF Mono,Menlo,monospace;font-size:11px;word-break:break-all;color:${labelFg}">'+escapeHtml(v[i].sql||'')+'</td><td style="padding:5px 8px;text-align:right;color:${sqlTimeClr};white-space:nowrap;font-family:ui-monospace,SF Mono,monospace;font-size:11px">'+escapeHtml(v[i].duration||'')+'</td></tr>';
|
|
55
68
|
}
|
|
56
69
|
continue;
|
|
57
70
|
}
|
|
58
71
|
if (k==='entries' && Array.isArray(v)) {
|
|
72
|
+
if (v.length===0) { h+='<tr><td style="padding:8px;color:${dimText}">No entries</td></tr>'; continue; }
|
|
59
73
|
for (var i=0;i<v.length;i++) {
|
|
60
74
|
var e=v[i];
|
|
61
75
|
var lc=e.level==='error'?'${errClr}':e.level==='warn'?'${warnClr}':'${dimText}';
|
|
62
|
-
|
|
76
|
+
var bgc=e.level==='error'?'rgba(239,68,68,0.08)':e.level==='warn'?'rgba(245,158,11,0.08)':'transparent';
|
|
77
|
+
h+='<tr style="background:'+bgc+'"><td style="padding:5px 8px;color:'+lc+';width:52px;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:0.3px">'+escapeHtml(e.level||'')+'</td><td style="padding:5px 8px;word-break:break-all;color:${labelFg}">'+escapeHtml(e.message||'')+'</td></tr>';
|
|
63
78
|
}
|
|
64
79
|
continue;
|
|
65
80
|
}
|
|
66
81
|
if (k==='grouped' && Array.isArray(v)) {
|
|
67
82
|
for (var i=0;i<v.length;i++) {
|
|
68
83
|
var g=v[i];
|
|
69
|
-
h+='<tr><td colspan="
|
|
84
|
+
h+='<tr><td colspan="2" style="padding:7px 8px 3px;color:${accent};font-weight:600;font-size:11px">'+escapeHtml(g.method||'')+' <span style="color:${dimText};font-weight:400">('+(g.count||0)+')</span></td></tr>';
|
|
70
85
|
if (g.routes) {
|
|
71
86
|
for (var j=0;j<g.routes.length;j++) {
|
|
72
|
-
h+='<tr><td style="padding:2px 8px 2px
|
|
87
|
+
h+='<tr><td style="padding:2px 8px 2px 16px;font-family:ui-monospace,SF Mono,monospace;font-size:11px;color:${labelFg}" colspan="2">'+escapeHtml(g.routes[j].path||'')+' <span style="color:${dimText}">('+escapeHtml(g.routes[j].controller||'')+')</span></td></tr>';
|
|
73
88
|
}
|
|
74
89
|
}
|
|
75
90
|
}
|
|
76
91
|
continue;
|
|
77
92
|
}
|
|
78
|
-
|
|
93
|
+
if (k==='exception' && v && typeof v==='object') {
|
|
94
|
+
h+='<tr><td style="padding:5px 8px;color:${errClr};font-weight:600" colspan="2">'+escapeHtml(v.message||'')+'</td></tr>';
|
|
95
|
+
h+='<tr><td colspan="2" style="padding:5px 8px"><pre style="font-family:ui-monospace,SF Mono,monospace;font-size:11px;color:${dimText};white-space:pre-wrap;margin:0;line-height:1.4">'+escapeHtml(v.stack||'')+'</pre></td></tr>';
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (k==='stack') continue;
|
|
99
|
+
if (typeof v==='object' && v!==null) continue;
|
|
100
|
+
h+='<tr><td style="padding:4px 8px;color:${dimText};width:90px;vertical-align:top;font-size:11px">'+escapeHtml(k)+'</td><td style="padding:4px 8px;word-break:break-all;color:${labelFg}">'+escapeHtml(String(v))+'</td></tr>';
|
|
79
101
|
}
|
|
80
102
|
h+='</table></div>';
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
D.getElementById(C+'-toggle').innerHTML='
|
|
103
|
+
pnl.innerHTML=h;
|
|
104
|
+
pnl.style.display='block';
|
|
105
|
+
D.getElementById(C+'-toggle').innerHTML='${I.chevron}';
|
|
84
106
|
}
|
|
85
107
|
|
|
86
108
|
function escapeHtml(s) {
|
|
87
109
|
if (s==null) return '';
|
|
88
|
-
return String(s).replace(
|
|
110
|
+
return String(s).replace(/[&<>"]/g,function(m){return {'&':'&','<':'<','>':'>','"':'"'}[m]});
|
|
89
111
|
}
|
|
90
112
|
|
|
113
|
+
var icons = {
|
|
114
|
+
request: '${I.req}',
|
|
115
|
+
performance: '${I.perf}',
|
|
116
|
+
database: '${I.db}',
|
|
117
|
+
routes: '${I.routes}',
|
|
118
|
+
logs: '${I.log}',
|
|
119
|
+
};
|
|
120
|
+
|
|
91
121
|
var furl = p + '/data';
|
|
92
122
|
fetch(furl).then(function(r){return r.json()}).then(function(d){
|
|
93
123
|
var bar=D.getElementById(C+'-bar');
|
|
124
|
+
var order=['request','performance','database','routes','logs'];
|
|
94
125
|
var panels=[];
|
|
95
|
-
if(d
|
|
96
|
-
if(d.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
for(var k in d){if(panels.indexOf(d[k])===-1&&d[k]&&d[k].label)panels.push(d[k]);}
|
|
101
|
-
var icons={request:'🌐',performance:'⚡',database:'🗄️',routes:'📋',logs:'📝','default':'🔧'};
|
|
102
|
-
panels.forEach(function(p,i){
|
|
103
|
-
var ic=icons[p.label.toLowerCase()]||icons['default'];
|
|
126
|
+
for(var oi=0;oi<order.length;oi++){if(d[order[oi]])panels.push({key:order[oi],data:d[order[oi]]});}
|
|
127
|
+
for(var k in d){var found=false;for(var pi=0;pi<panels.length;pi++){if(panels[pi].key===k){found=true;break}}if(!found&&d[k]&&d[k].label)panels.push({key:k,data:d[k]});}
|
|
128
|
+
panels.forEach(function(item,idx){
|
|
129
|
+
var p=item.data;
|
|
130
|
+
var ic=icons[item.key]||'${I.log}';
|
|
104
131
|
var btn=D.createElement('span');
|
|
105
|
-
btn.style.cssText='display:inline-flex;align-items:center;gap:
|
|
106
|
-
btn.innerHTML=ic+'
|
|
107
|
-
btn.onmouseenter=function(){this.style.background='${btnHover}'};
|
|
108
|
-
btn.onmouseleave=function(){this.style.background='${btnBg}'};
|
|
132
|
+
btn.style.cssText='display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:6px;cursor:pointer;color:${btnFg};background:${btnBg};margin:0 1px;transition:all .12s ease;font-size:11px;font-weight:500';
|
|
133
|
+
btn.innerHTML=ic+'<span>'+escapeHtml(p.summary)+'</span>';
|
|
134
|
+
btn.onmouseenter=function(){this.style.background='${btnHover}';this.style.color='${fg}'};
|
|
135
|
+
btn.onmouseleave=function(){this.style.background='${btnBg}';this.style.color='${btnFg}'};
|
|
109
136
|
btn.onclick=function(n){return function(){
|
|
110
|
-
var key=Object.keys(d).filter(function(
|
|
137
|
+
var key=Object.keys(d).filter(function(kr){return d[kr]===d[n]})[0];
|
|
111
138
|
renderPanel(key,d[key]);
|
|
112
|
-
}}(
|
|
139
|
+
}}(item.key);
|
|
113
140
|
bar.appendChild(btn);
|
|
114
141
|
});
|
|
115
142
|
D.getElementById(C+'-toggle').onclick=function(){
|
|
116
143
|
var pnl=D.getElementById(C+'-panel');
|
|
117
|
-
|
|
118
|
-
|
|
144
|
+
var isOpen=pnl.style.display==='block';
|
|
145
|
+
pnl.style.display=isOpen?'none':'block';
|
|
146
|
+
this.innerHTML=isOpen?'${I.chevron}':'${I.close}';
|
|
147
|
+
if(isOpen)lastActive=null;
|
|
119
148
|
};
|
|
120
149
|
}).catch(function(){});
|
|
121
150
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../toolbar/template.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../toolbar/template.ts"],"names":[],"mappings":"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"}
|