@tezx/devtools 1.0.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/LICENSE +21 -0
- package/README.md +1 -0
- package/cjs/devtools/dumpRoutes.js +41 -0
- package/cjs/devtools/index.js +17 -0
- package/cjs/devtools/middlewares.js +23 -0
- package/cjs/html/cookies.js +145 -0
- package/cjs/html/index.js +22 -0
- package/cjs/html/routes.js +160 -0
- package/cjs/index.js +312 -0
- package/devtools/dumpRoutes.d.ts +9 -0
- package/devtools/dumpRoutes.js +38 -0
- package/devtools/index.d.ts +10 -0
- package/devtools/index.js +12 -0
- package/devtools/middlewares.d.ts +7 -0
- package/devtools/middlewares.js +20 -0
- package/html/cookies.d.ts +2 -0
- package/html/cookies.js +142 -0
- package/html/index.d.ts +9 -0
- package/html/index.js +19 -0
- package/html/routes.d.ts +2 -0
- package/html/routes.js +157 -0
- package/index.d.ts +8 -0
- package/index.js +309 -0
- package/package.json +55 -0
package/html/routes.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { dumpRoutes } from "../devtools";
|
|
2
|
+
export function Routes(ctx, app) {
|
|
3
|
+
const allRoutes = dumpRoutes(app);
|
|
4
|
+
const totalRoutes = allRoutes.length;
|
|
5
|
+
const middlewareStats = {};
|
|
6
|
+
const middlewareRoutes = {};
|
|
7
|
+
for (const route of allRoutes) {
|
|
8
|
+
for (const mw of route.appliedMiddlewares || []) {
|
|
9
|
+
middlewareStats[mw] = (middlewareStats[mw] || 0) + 1;
|
|
10
|
+
(middlewareRoutes[mw] ||= []).push(route);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const rawJSON = JSON.stringify(allRoutes, null, 2);
|
|
14
|
+
const toCSV = (data) => {
|
|
15
|
+
const headers = ['method', 'match', 'userPath', 'routePattern', 'appliedMiddlewares'];
|
|
16
|
+
const csvRows = [
|
|
17
|
+
headers.join(','),
|
|
18
|
+
...data.map(r => headers.map(h => JSON.stringify(r[h] ?? '')).join(','))
|
|
19
|
+
];
|
|
20
|
+
return csvRows.join('\n');
|
|
21
|
+
};
|
|
22
|
+
const csvString = toCSV(allRoutes).replace(/"/g, '"');
|
|
23
|
+
return `
|
|
24
|
+
<style>
|
|
25
|
+
.download {
|
|
26
|
+
margin-top: 1rem;
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 1rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.download a {
|
|
32
|
+
padding: 0.5rem 1rem;
|
|
33
|
+
border: 1px solid var(--accent);
|
|
34
|
+
color: var(--accent);
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
border-radius: 6px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.download a:hover {
|
|
40
|
+
background: var(--accent);
|
|
41
|
+
color: white;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#searchBar {
|
|
45
|
+
margin: 1rem 0;
|
|
46
|
+
display: flex;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#searchBar input {
|
|
50
|
+
flex: 1;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
53
|
+
|
|
54
|
+
<div class="tabs">
|
|
55
|
+
<a class="tab-btn active counting" data-count="${totalRoutes}" onclick="showTab('routes')">๐ Routes</a>
|
|
56
|
+
<a class="tab-btn counting" data-count="${Object.keys(middlewareStats).length}" onclick="showTab('stats')">๐
|
|
57
|
+
Stats</a>
|
|
58
|
+
<a class="tab-btn" onclick="showTab('middlewares')">๐งฉ Middlewares</a>
|
|
59
|
+
<a class="tab-btn" onclick="showTab('json')">๐งพ Raw JSON</a>
|
|
60
|
+
<a class="tab-btn" onclick="showTab('export')">๐ค Export</a>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div id="searchBar" style="display:flex">
|
|
64
|
+
<input type="text" id="search" placeholder="Filter by method/path/middleware..." />
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- ROUTES -->
|
|
68
|
+
<div id="routesTab">
|
|
69
|
+
<table id="routesTable">
|
|
70
|
+
<thead>
|
|
71
|
+
<tr>
|
|
72
|
+
<th>#</th>
|
|
73
|
+
<th>Method</th>
|
|
74
|
+
<th>Match</th>
|
|
75
|
+
<th>User Path</th>
|
|
76
|
+
<th>Route Pattern</th>
|
|
77
|
+
<th>Middlewares</th>
|
|
78
|
+
</tr>
|
|
79
|
+
</thead>
|
|
80
|
+
<tbody>
|
|
81
|
+
${allRoutes.map((r, i) => `
|
|
82
|
+
<tr>
|
|
83
|
+
<td>${i + 1}</td>
|
|
84
|
+
<td>${r.method}</td>
|
|
85
|
+
<td>${r.match}</td>
|
|
86
|
+
<td>${r.userPath}</td>
|
|
87
|
+
<td>${r.routePattern}</td>
|
|
88
|
+
<td>${(r.appliedMiddlewares || []).join(', ')}</td>
|
|
89
|
+
</tr>`).join('')}
|
|
90
|
+
</tbody>
|
|
91
|
+
</table>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<!-- STATS -->
|
|
95
|
+
<div id="statsTab" style="display:none">
|
|
96
|
+
<div class="json-view">
|
|
97
|
+
Total Routes: ${totalRoutes}
|
|
98
|
+
Middleware Used: ${Object.keys(middlewareStats).length}
|
|
99
|
+
|
|
100
|
+
${Object.entries(middlewareStats).map(([mw, count]) => `- ${mw}: ${count} routes`).join('\n')}
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<!-- MIDDLEWARES -->
|
|
105
|
+
<div id="middlewaresTab" style="display:none">
|
|
106
|
+
${Object.entries(middlewareRoutes).map(([mw, routes]) => `
|
|
107
|
+
<h3>๐น ${mw} (${routes.length})</h3>
|
|
108
|
+
<ul>
|
|
109
|
+
${routes.map(r => `<li><code>${r.method} ${r.userPath}</code></li>`).join('')}
|
|
110
|
+
</ul>
|
|
111
|
+
`).join('')}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<!-- RAW JSON -->
|
|
115
|
+
<div id="jsonTab" style="display:none">
|
|
116
|
+
<div class="json-view">${rawJSON}</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<!-- EXPORT -->
|
|
120
|
+
<div id="exportTab" style="display:none">
|
|
121
|
+
<div class="download">
|
|
122
|
+
<a href="data:text/json;charset=utf-8,${encodeURIComponent(rawJSON)}" download="routes.json">๐ฅ JSON</a>
|
|
123
|
+
<a href="data:text/csv;charset=utf-8,${csvString}" download="routes.csv">๐ฅ CSV</a>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<script>
|
|
128
|
+
const tabs = ['routes', 'stats', 'middlewares', 'json', 'export'];
|
|
129
|
+
const tabBtns = document.querySelectorAll('.tab-btn');
|
|
130
|
+
|
|
131
|
+
function showTab(tab) {
|
|
132
|
+
tabs.forEach(t => {
|
|
133
|
+
document.getElementById(t + 'Tab').style.display = t === tab ? 'block' : 'none';
|
|
134
|
+
if (t === tab) {
|
|
135
|
+
document.getElementById(t + 'Tab').classList.add('active');
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
document.getElementById(t + 'Tab').classList.remove('active');
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
tabBtns.forEach(btn => {
|
|
142
|
+
const active = btn.textContent.toLowerCase().includes(tab);
|
|
143
|
+
btn.classList.toggle('active', active);
|
|
144
|
+
});
|
|
145
|
+
document.getElementById('searchBar').style.display = (tab === 'routes') ? 'flex' : 'none';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
document.getElementById('search').addEventListener('input', (e) => {
|
|
149
|
+
const keyword = e.target.value.toLowerCase();
|
|
150
|
+
const rows = document.querySelectorAll('#routesTable tbody tr');
|
|
151
|
+
rows.forEach(row => {
|
|
152
|
+
row.style.display = row.textContent.toLowerCase().includes(keyword) ? '' : 'none';
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
</script>
|
|
156
|
+
`;
|
|
157
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Callback, TezX } from "tezx";
|
|
2
|
+
import { Tab, TabType } from "./html/index.js";
|
|
3
|
+
export type Options = {
|
|
4
|
+
extraTabs?: TabType;
|
|
5
|
+
disableTabs?: Tab[];
|
|
6
|
+
};
|
|
7
|
+
export declare function DevTools(app: TezX, options?: Options): Callback;
|
|
8
|
+
export default DevTools;
|
package/index.js
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { html as htmlTab } from "./html/index.js";
|
|
2
|
+
export function DevTools(app, options = { disableTabs: [], extraTabs: [] }) {
|
|
3
|
+
let { disableTabs, extraTabs } = options;
|
|
4
|
+
return (ctx) => {
|
|
5
|
+
let html = [...(disableTabs?.length ? htmlTab(ctx, app)?.filter(r => !disableTabs?.includes(r?.tab)) : htmlTab(ctx, app)), ...extraTabs || []];
|
|
6
|
+
let tab = ctx.req.query?._tab || html?.[0]?.tab;
|
|
7
|
+
const navbar = `
|
|
8
|
+
<header>
|
|
9
|
+
<div class="tabs">
|
|
10
|
+
<img src="http://papernxt.com/favicon.ico" style="height:32px;"/>
|
|
11
|
+
${html?.map(r => `<a href = "?_tab=${r?.tab}" class="${tab === r?.tab ? 'active' : ''}" > ${r?.label} </a>`)?.join('\n')}
|
|
12
|
+
</div>
|
|
13
|
+
<div class="tabs">
|
|
14
|
+
<a class="toggle-dark" onclick="toggleTheme()">๐ Toggle Dark</a>
|
|
15
|
+
</div>
|
|
16
|
+
</header>
|
|
17
|
+
`;
|
|
18
|
+
let find = html.find(r => r?.tab == tab);
|
|
19
|
+
return ctx.html `
|
|
20
|
+
<!DOCTYPE html>
|
|
21
|
+
<html lang="en">
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="UTF-8" />
|
|
24
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
25
|
+
<title>${find?.doc_title}</title>
|
|
26
|
+
<style>
|
|
27
|
+
:root {
|
|
28
|
+
--bg: #f8f9fa;
|
|
29
|
+
--text: #212529;
|
|
30
|
+
--accent: #FF581E;
|
|
31
|
+
--header-bg: rgba(255, 255, 255, 0.94);
|
|
32
|
+
--table-bg: #ffffff;
|
|
33
|
+
--table-border: #d1d5db;
|
|
34
|
+
/* Gray-300 */
|
|
35
|
+
--tr-hover: #e3f2fd;
|
|
36
|
+
/* Light Blue Hover */
|
|
37
|
+
--tr-odd: #f8fafc;
|
|
38
|
+
/* Lightest gray-blue */
|
|
39
|
+
--tr-even: #ffffff;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
body.dark {
|
|
43
|
+
--bg: #0e1117;
|
|
44
|
+
--text: #f1f3f5;
|
|
45
|
+
--accent: #58a6ff;
|
|
46
|
+
/* GitHub Blue */
|
|
47
|
+
--header-bg: rgba(18, 18, 18, 0.9);
|
|
48
|
+
--table-bg: #161b22;
|
|
49
|
+
--table-border: #30363d;
|
|
50
|
+
--tr-hover: #1f6feb33;
|
|
51
|
+
/* Blue hover with opacity */
|
|
52
|
+
--tr-odd: #1a1f24;
|
|
53
|
+
--tr-even: #0f1419;
|
|
54
|
+
|
|
55
|
+
--col-1: #9ca3af;
|
|
56
|
+
/* Gray-400 */
|
|
57
|
+
--col-2: #58a6ff;
|
|
58
|
+
/* Blue-300 */
|
|
59
|
+
--col-3: #4ade80;
|
|
60
|
+
/* Green-400 */
|
|
61
|
+
--col-4: #facc15;
|
|
62
|
+
/* Yellow-400 */
|
|
63
|
+
--col-5: #c084fc;
|
|
64
|
+
/* Purple-400 */
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
body {
|
|
68
|
+
margin: 0;
|
|
69
|
+
font-family: system-ui, sans-serif;
|
|
70
|
+
background: var(--bg);
|
|
71
|
+
color: var(--text);
|
|
72
|
+
transition: background 0.3s ease, color 0.3s ease;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
header {
|
|
77
|
+
position: sticky;
|
|
78
|
+
background: var(--header-bg);
|
|
79
|
+
border-bottom: 1px solid var(--accent);
|
|
80
|
+
top: 0px;
|
|
81
|
+
display: flex;
|
|
82
|
+
padding: 16px;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: space-between;
|
|
85
|
+
gap: 6px;
|
|
86
|
+
flex-wrap: wrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
header>div {
|
|
90
|
+
display: flex;
|
|
91
|
+
gap: 6px;
|
|
92
|
+
align-items: center;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.tabs a {
|
|
96
|
+
padding: 0.4rem 0.8rem;
|
|
97
|
+
text-decoration: none;
|
|
98
|
+
border: 1px solid var(--accent);
|
|
99
|
+
border-radius: 5px;
|
|
100
|
+
color: var(--accent);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
text-transform: capitalize;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tabs a.active {
|
|
106
|
+
background-color: var(--accent);
|
|
107
|
+
color: white;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
.tabs a.counting::after {
|
|
112
|
+
content: attr(data-count);
|
|
113
|
+
background: var(--accent);
|
|
114
|
+
color: white;
|
|
115
|
+
font-size: 0.7rem;
|
|
116
|
+
margin-left: 6px;
|
|
117
|
+
padding: 2px 6px;
|
|
118
|
+
border-radius: 10px;
|
|
119
|
+
display: inline-block;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.tabs a.counting.active::after {
|
|
123
|
+
content: attr(data-count);
|
|
124
|
+
background: white;
|
|
125
|
+
color: black;
|
|
126
|
+
font-size: 0.7rem;
|
|
127
|
+
margin-left: 6px;
|
|
128
|
+
padding: 2px 6px;
|
|
129
|
+
border-radius: 10px;
|
|
130
|
+
display: inline-block;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
section.content {
|
|
134
|
+
padding: 16px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
h1 {
|
|
138
|
+
font-size: 1.8rem;
|
|
139
|
+
margin-top: 0px;
|
|
140
|
+
margin-bottom: 20px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
input[type="text"] {
|
|
144
|
+
display: inline-flex;
|
|
145
|
+
margin-top: 16px;
|
|
146
|
+
padding: 0.5rem;
|
|
147
|
+
font-size: 1rem;
|
|
148
|
+
border: 1px solid var(--table-border);
|
|
149
|
+
border-radius: 6px;
|
|
150
|
+
max-width: 300px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
input[type="text"]:focus {
|
|
154
|
+
outline: 1px solid var(--accent);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.match-true {
|
|
158
|
+
color: green;
|
|
159
|
+
font-weight: bold;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.match-false {
|
|
163
|
+
color: red;
|
|
164
|
+
font-weight: bold;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.json-view {
|
|
168
|
+
margin-top: 16px;
|
|
169
|
+
white-space: pre-wrap;
|
|
170
|
+
background: var(--table-bg);
|
|
171
|
+
padding: 1rem;
|
|
172
|
+
border: 1px solid var(--table-border);
|
|
173
|
+
border-radius: 6px;
|
|
174
|
+
font-family: monospace;
|
|
175
|
+
max-height: 600px;
|
|
176
|
+
overflow: auto;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.table-container {
|
|
180
|
+
overflow-x: auto;
|
|
181
|
+
border-radius: 0.5rem;
|
|
182
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
table {
|
|
186
|
+
width: 100%;
|
|
187
|
+
border-collapse: collapse;
|
|
188
|
+
background: var(--table-bg);
|
|
189
|
+
margin-top: 1rem;
|
|
190
|
+
border: 1px solid var(--table-border);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
th,
|
|
194
|
+
td {
|
|
195
|
+
padding: 0.75rem;
|
|
196
|
+
text-align: left;
|
|
197
|
+
border: 1px solid var(--table-border);
|
|
198
|
+
font-size: 0.95rem;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
thead {
|
|
202
|
+
background-color: var(--accent);
|
|
203
|
+
color: white;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Light mode zebra striping */
|
|
207
|
+
tbody tr:nth-child(odd) {
|
|
208
|
+
background-color: var(--tr-odd);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
tbody tr:nth-child(even) {
|
|
212
|
+
background-color: var(--tr-even);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* Hover effect */
|
|
216
|
+
tbody tr:hover {
|
|
217
|
+
background-color: var(--tr-hover);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.status-true {
|
|
221
|
+
color: green;
|
|
222
|
+
font-weight: bold;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.status-false {
|
|
226
|
+
color: red;
|
|
227
|
+
font-weight: bold;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@media (max-width: 768px) {
|
|
231
|
+
|
|
232
|
+
table,
|
|
233
|
+
thead,
|
|
234
|
+
tbody,
|
|
235
|
+
th,
|
|
236
|
+
td,
|
|
237
|
+
tr {
|
|
238
|
+
display: block;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
thead {
|
|
242
|
+
display: none;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
tr {
|
|
246
|
+
margin-bottom: 1rem;
|
|
247
|
+
border: 1px solid var(--table-border);
|
|
248
|
+
border-radius: 8px;
|
|
249
|
+
background: var(--table-bg);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
td {
|
|
253
|
+
display: flex;
|
|
254
|
+
justify-content: space-between;
|
|
255
|
+
padding: 0.5rem 1rem;
|
|
256
|
+
border: none;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
td::before {
|
|
260
|
+
content: attr(data-label);
|
|
261
|
+
font-weight: bold;
|
|
262
|
+
color: var(--accent);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
266
|
+
</head>
|
|
267
|
+
<body>
|
|
268
|
+
${navbar}
|
|
269
|
+
|
|
270
|
+
<section class="content">
|
|
271
|
+
<h1>
|
|
272
|
+
${find?.doc_title}
|
|
273
|
+
</h1>
|
|
274
|
+
${find?.content}
|
|
275
|
+
<section>
|
|
276
|
+
<script>
|
|
277
|
+
|
|
278
|
+
const themeCookieName = "tezx-theme";
|
|
279
|
+
|
|
280
|
+
function setCookie(name, value, days = 30) {
|
|
281
|
+
const expires = new Date(Date.now() + days * 864e5).toUTCString();
|
|
282
|
+
document.cookie = ${"`${ name }=${ value }; expires = ${ expires }; path =/`"};
|
|
283
|
+
}
|
|
284
|
+
function getCookie(name) {
|
|
285
|
+
return document.cookie.split('; ').reduce((acc, cookie) => {
|
|
286
|
+
const [key, val] = cookie.split('=');
|
|
287
|
+
return key === name ? decodeURIComponent(val) : acc;
|
|
288
|
+
}, null);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function toggleTheme() {
|
|
292
|
+
document.body.classList.toggle('dark');
|
|
293
|
+
setCookie(themeCookieName, document.body.classList.contains('dark') ? 'dark' : 'light');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Load theme from cookie
|
|
297
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
298
|
+
const savedTheme = getCookie(themeCookieName);
|
|
299
|
+
if (savedTheme === 'dark') {
|
|
300
|
+
document.body.classList.add('dark');
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
</script>
|
|
304
|
+
</body>
|
|
305
|
+
</html>
|
|
306
|
+
`;
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
export default DevTools;
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tezx/devtools",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Developer tools for the TezX framework, including route inspector, cookie manager, and real-time diagnostics. Lightweight and plug-and-play compatible with Node.js, Bun, and Deno.",
|
|
5
|
+
"main": "cjs/index.js",
|
|
6
|
+
"module": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"typings": "index.d.ts",
|
|
9
|
+
"scripts": {},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/tezxjs/devtools.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/tezxjs/devtools/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/tezxjs/devtools#readme",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./index.js",
|
|
21
|
+
"require": "./cjs/index.js",
|
|
22
|
+
"types": "./index.d.ts",
|
|
23
|
+
"default": "./index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"cjs/",
|
|
28
|
+
"devtools/",
|
|
29
|
+
"html/",
|
|
30
|
+
"index.js",
|
|
31
|
+
"index.d.ts"
|
|
32
|
+
],
|
|
33
|
+
"keywords": [
|
|
34
|
+
"devtools",
|
|
35
|
+
"tezx",
|
|
36
|
+
"debugging",
|
|
37
|
+
"developer-tools",
|
|
38
|
+
"route-inspector",
|
|
39
|
+
"cookie-manager",
|
|
40
|
+
"inspector",
|
|
41
|
+
"nodejs",
|
|
42
|
+
"bun",
|
|
43
|
+
"deno"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=18",
|
|
50
|
+
"bun": ">=1.0",
|
|
51
|
+
"deno": ">=1.36"
|
|
52
|
+
},
|
|
53
|
+
"author": "SRAKIB17",
|
|
54
|
+
"license": "MIT"
|
|
55
|
+
}
|