serverreq 1.1.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 +194 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +186 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +78 -0
- package/dist/config.js.map +1 -0
- package/dist/devtools/event-bus.d.ts +12 -0
- package/dist/devtools/event-bus.d.ts.map +1 -0
- package/dist/devtools/event-bus.js +47 -0
- package/dist/devtools/event-bus.js.map +1 -0
- package/dist/devtools/index.d.ts +25 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/index.js +55 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/devtools/panel.d.ts +19 -0
- package/dist/devtools/panel.d.ts.map +1 -0
- package/dist/devtools/panel.js +308 -0
- package/dist/devtools/panel.js.map +1 -0
- package/dist/devtools/server.d.ts +39 -0
- package/dist/devtools/server.d.ts.map +1 -0
- package/dist/devtools/server.js +184 -0
- package/dist/devtools/server.js.map +1 -0
- package/dist/devtools/sse-handler.d.ts +5 -0
- package/dist/devtools/sse-handler.d.ts.map +1 -0
- package/dist/devtools/sse-handler.js +92 -0
- package/dist/devtools/sse-handler.js.map +1 -0
- package/dist/devtools/store.d.ts +31 -0
- package/dist/devtools/store.d.ts.map +1 -0
- package/dist/devtools/store.js +145 -0
- package/dist/devtools/store.js.map +1 -0
- package/dist/devtools/types.d.ts +45 -0
- package/dist/devtools/types.d.ts.map +1 -0
- package/dist/devtools/types.js +18 -0
- package/dist/devtools/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor.d.ts +14 -0
- package/dist/interceptor.d.ts.map +1 -0
- package/dist/interceptor.js +404 -0
- package/dist/interceptor.js.map +1 -0
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +123 -0
- package/dist/logger.js.map +1 -0
- package/dist/nextjs.d.ts +43 -0
- package/dist/nextjs.d.ts.map +1 -0
- package/dist/nextjs.js +55 -0
- package/dist/nextjs.js.map +1 -0
- package/dist/preload.d.ts +2 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +24 -0
- package/dist/preload.js.map +1 -0
- package/dist/test-interceptor.d.ts +5 -0
- package/dist/test-interceptor.d.ts.map +1 -0
- package/dist/test-interceptor.js +113 -0
- package/dist/test-interceptor.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP/HTTPS Interceptor for Node.js >= 18
|
|
4
|
+
* Patches globalThis.fetch, http.request, and https.request to log all outgoing requests and responses.
|
|
5
|
+
* Compatible with Next.js (App Router, Server Actions, etc.)
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.install = install;
|
|
42
|
+
exports.uninstall = uninstall;
|
|
43
|
+
const config_1 = require("./config");
|
|
44
|
+
const logger_1 = require("./logger");
|
|
45
|
+
const event_bus_1 = require("./devtools/event-bus");
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
// Store original implementations
|
|
48
|
+
let originalFetch;
|
|
49
|
+
let originalHttpRequest;
|
|
50
|
+
let originalHttpsRequest;
|
|
51
|
+
let isInstalled = false;
|
|
52
|
+
/**
|
|
53
|
+
* Patches globalThis.fetch to intercept and log requests/responses
|
|
54
|
+
*/
|
|
55
|
+
function patchFetch() {
|
|
56
|
+
if (typeof globalThis.fetch === 'undefined') {
|
|
57
|
+
return; // fetch not available
|
|
58
|
+
}
|
|
59
|
+
originalFetch = globalThis.fetch;
|
|
60
|
+
globalThis.fetch = async function (input, init) {
|
|
61
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
62
|
+
const method = init?.method || (typeof input === 'object' && 'method' in input ? input.method : 'GET');
|
|
63
|
+
// Check if URL should be excluded
|
|
64
|
+
const config = (0, config_1.getConfig)();
|
|
65
|
+
if (!config.shouldLogRequest(url)) {
|
|
66
|
+
return originalFetch(input, init);
|
|
67
|
+
}
|
|
68
|
+
const requestHeaders = init?.headers ? headersToObject(init.headers) :
|
|
69
|
+
(typeof input === 'object' && 'headers' in input && input.headers ? headersToObject(input.headers) : {});
|
|
70
|
+
const requestBody = init?.body ? await bodyToString(init.body) : '';
|
|
71
|
+
const startTime = Date.now();
|
|
72
|
+
// Log request
|
|
73
|
+
logger_1.Logger.log({
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
method,
|
|
76
|
+
url,
|
|
77
|
+
headers: requestHeaders,
|
|
78
|
+
body: requestBody || undefined,
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
// Make the actual request
|
|
82
|
+
const response = await originalFetch(input, init);
|
|
83
|
+
// Clone response to read body without consuming original
|
|
84
|
+
const clonedResponse = response.clone();
|
|
85
|
+
const responseBody = await clonedResponse.text().catch(() => '[Unable to read response body]');
|
|
86
|
+
const responseHeaders = headersToObject(clonedResponse.headers);
|
|
87
|
+
// Log response
|
|
88
|
+
logger_1.Logger.log({
|
|
89
|
+
timestamp: new Date().toISOString(),
|
|
90
|
+
method: `${method} RESPONSE`,
|
|
91
|
+
url: `${url} [${response.status}]`,
|
|
92
|
+
headers: responseHeaders,
|
|
93
|
+
body: responseBody || undefined,
|
|
94
|
+
});
|
|
95
|
+
// Emit to DevTools (Global Bus)
|
|
96
|
+
event_bus_1.eventBus.emit('network:event', {
|
|
97
|
+
id: crypto.randomUUID(),
|
|
98
|
+
timestamp: startTime,
|
|
99
|
+
method,
|
|
100
|
+
url,
|
|
101
|
+
requestHeaders,
|
|
102
|
+
requestBody,
|
|
103
|
+
status: response.status,
|
|
104
|
+
responseHeaders,
|
|
105
|
+
responseBody,
|
|
106
|
+
duration: Date.now() - startTime
|
|
107
|
+
});
|
|
108
|
+
return response;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
// Log error
|
|
112
|
+
logger_1.Logger.log({
|
|
113
|
+
timestamp: new Date().toISOString(),
|
|
114
|
+
method: `${method} ERROR`,
|
|
115
|
+
url,
|
|
116
|
+
headers: {},
|
|
117
|
+
body: error instanceof Error ? error.message : String(error),
|
|
118
|
+
});
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Converts Headers object to plain object
|
|
125
|
+
*/
|
|
126
|
+
function headersToObject(headers) {
|
|
127
|
+
const obj = {};
|
|
128
|
+
if (headers instanceof Headers) {
|
|
129
|
+
headers.forEach((value, key) => {
|
|
130
|
+
obj[key] = value;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else if (Array.isArray(headers)) {
|
|
134
|
+
headers.forEach(([key, value]) => {
|
|
135
|
+
obj[key] = value;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else if (headers) {
|
|
139
|
+
Object.assign(obj, headers);
|
|
140
|
+
}
|
|
141
|
+
return obj;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Converts various body types to string
|
|
145
|
+
*/
|
|
146
|
+
async function bodyToString(body) {
|
|
147
|
+
if (typeof body === 'string') {
|
|
148
|
+
return body;
|
|
149
|
+
}
|
|
150
|
+
if (body instanceof URLSearchParams) {
|
|
151
|
+
return body.toString();
|
|
152
|
+
}
|
|
153
|
+
if (body instanceof Blob) {
|
|
154
|
+
return await body.text();
|
|
155
|
+
}
|
|
156
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
|
|
157
|
+
const buffer = body instanceof ArrayBuffer ? body : body.buffer;
|
|
158
|
+
return Buffer.from(buffer).toString('utf-8');
|
|
159
|
+
}
|
|
160
|
+
if (body && typeof body.pipe === 'function') {
|
|
161
|
+
// ReadableStream - don't consume it
|
|
162
|
+
return '[Stream]';
|
|
163
|
+
}
|
|
164
|
+
return String(body);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Patches http.request to intercept and log requests/responses
|
|
168
|
+
*/
|
|
169
|
+
function patchHttpRequest() {
|
|
170
|
+
// Use require to get mutable reference
|
|
171
|
+
const http = require('http');
|
|
172
|
+
originalHttpRequest = http.request;
|
|
173
|
+
http.request = function (url, options, callback) {
|
|
174
|
+
// Parse arguments (http.request has multiple signatures)
|
|
175
|
+
let opts;
|
|
176
|
+
let cb;
|
|
177
|
+
if (typeof url === 'string' || url instanceof URL) {
|
|
178
|
+
opts = options || {};
|
|
179
|
+
cb = callback;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
opts = url;
|
|
183
|
+
cb = options;
|
|
184
|
+
}
|
|
185
|
+
const fullUrl = buildUrl(opts, 'http:');
|
|
186
|
+
const method = opts.method || 'GET';
|
|
187
|
+
// Check if URL should be excluded
|
|
188
|
+
const config = (0, config_1.getConfig)();
|
|
189
|
+
if (!config.shouldLogRequest(fullUrl)) {
|
|
190
|
+
return originalHttpRequest.apply(this, arguments);
|
|
191
|
+
}
|
|
192
|
+
const requestHeaders = opts.headers ? { ...opts.headers } : {};
|
|
193
|
+
const startTime = Date.now();
|
|
194
|
+
// Intercept the callback to log response
|
|
195
|
+
const wrappedCallback = cb ? (res) => {
|
|
196
|
+
interceptResponse(res, method, fullUrl, requestHeaders, requestBody, startTime);
|
|
197
|
+
cb(res);
|
|
198
|
+
} : undefined;
|
|
199
|
+
// Call original with wrapped callback
|
|
200
|
+
const req = originalHttpRequest.call(this, url, wrappedCallback ? { ...opts, headers: requestHeaders } : opts, wrappedCallback);
|
|
201
|
+
// Intercept write to capture request body
|
|
202
|
+
const originalWrite = req.write.bind(req);
|
|
203
|
+
const originalEnd = req.end.bind(req);
|
|
204
|
+
let requestBody = '';
|
|
205
|
+
req.write = function (chunk, encoding, callback) {
|
|
206
|
+
if (chunk) {
|
|
207
|
+
requestBody += chunk.toString();
|
|
208
|
+
}
|
|
209
|
+
return originalWrite(chunk, encoding, callback);
|
|
210
|
+
};
|
|
211
|
+
req.end = function (chunk, encoding, callback) {
|
|
212
|
+
if (chunk) {
|
|
213
|
+
requestBody += chunk.toString();
|
|
214
|
+
}
|
|
215
|
+
// Log request
|
|
216
|
+
logger_1.Logger.log({
|
|
217
|
+
timestamp: new Date().toISOString(),
|
|
218
|
+
method,
|
|
219
|
+
url: fullUrl,
|
|
220
|
+
headers: requestHeaders,
|
|
221
|
+
body: requestBody || undefined,
|
|
222
|
+
});
|
|
223
|
+
return originalEnd(chunk, encoding, callback);
|
|
224
|
+
};
|
|
225
|
+
// Handle case where callback wasn't provided
|
|
226
|
+
if (!cb) {
|
|
227
|
+
req.on('response', (res) => {
|
|
228
|
+
interceptResponse(res, method, fullUrl, requestHeaders, requestBody, startTime);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return req;
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Patches https.request to intercept and log requests/responses
|
|
236
|
+
*/
|
|
237
|
+
function patchHttpsRequest() {
|
|
238
|
+
// Use require to get mutable reference
|
|
239
|
+
const https = require('https');
|
|
240
|
+
originalHttpsRequest = https.request;
|
|
241
|
+
https.request = function (url, options, callback) {
|
|
242
|
+
// Parse arguments
|
|
243
|
+
let opts;
|
|
244
|
+
let cb;
|
|
245
|
+
if (typeof url === 'string' || url instanceof URL) {
|
|
246
|
+
opts = options || {};
|
|
247
|
+
cb = callback;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
opts = url;
|
|
251
|
+
cb = options;
|
|
252
|
+
}
|
|
253
|
+
const fullUrl = buildUrl(opts, 'https:');
|
|
254
|
+
const method = opts.method || 'GET';
|
|
255
|
+
// Check if URL should be excluded
|
|
256
|
+
const config = (0, config_1.getConfig)();
|
|
257
|
+
if (!config.shouldLogRequest(fullUrl)) {
|
|
258
|
+
return originalHttpsRequest.apply(this, arguments);
|
|
259
|
+
}
|
|
260
|
+
const requestHeaders = opts.headers ? { ...opts.headers } : {};
|
|
261
|
+
const startTime = Date.now();
|
|
262
|
+
// Intercept the callback to log response
|
|
263
|
+
const wrappedCallback = cb ? (res) => {
|
|
264
|
+
interceptResponse(res, method, fullUrl, requestHeaders, requestBody, startTime);
|
|
265
|
+
cb(res);
|
|
266
|
+
} : undefined;
|
|
267
|
+
// Call original with wrapped callback
|
|
268
|
+
const req = originalHttpsRequest.call(this, url, wrappedCallback ? { ...opts, headers: requestHeaders } : opts, wrappedCallback);
|
|
269
|
+
// Intercept write to capture request body
|
|
270
|
+
const originalWrite = req.write.bind(req);
|
|
271
|
+
const originalEnd = req.end.bind(req);
|
|
272
|
+
let requestBody = '';
|
|
273
|
+
req.write = function (chunk, encoding, callback) {
|
|
274
|
+
if (chunk) {
|
|
275
|
+
requestBody += chunk.toString();
|
|
276
|
+
}
|
|
277
|
+
return originalWrite(chunk, encoding, callback);
|
|
278
|
+
};
|
|
279
|
+
req.end = function (chunk, encoding, callback) {
|
|
280
|
+
if (chunk) {
|
|
281
|
+
requestBody += chunk.toString();
|
|
282
|
+
}
|
|
283
|
+
// Log request
|
|
284
|
+
logger_1.Logger.log({
|
|
285
|
+
timestamp: new Date().toISOString(),
|
|
286
|
+
method,
|
|
287
|
+
url: fullUrl,
|
|
288
|
+
headers: requestHeaders,
|
|
289
|
+
body: requestBody || undefined,
|
|
290
|
+
});
|
|
291
|
+
return originalEnd(chunk, encoding, callback);
|
|
292
|
+
};
|
|
293
|
+
// Handle case where callback wasn't provided
|
|
294
|
+
if (!cb) {
|
|
295
|
+
req.on('response', (res) => {
|
|
296
|
+
interceptResponse(res, method, fullUrl, requestHeaders, requestBody, startTime);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return req;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Intercepts and logs HTTP response
|
|
304
|
+
*/
|
|
305
|
+
function interceptResponse(res, method, url, requestHeaders, requestBody, startTime) {
|
|
306
|
+
const responseHeaders = res.headers;
|
|
307
|
+
let responseBody = '';
|
|
308
|
+
// Collect response body chunks
|
|
309
|
+
const originalOn = res.on.bind(res);
|
|
310
|
+
res.on = function (event, listener) {
|
|
311
|
+
if (event === 'data') {
|
|
312
|
+
const wrappedListener = (chunk) => {
|
|
313
|
+
responseBody += chunk.toString();
|
|
314
|
+
listener(chunk);
|
|
315
|
+
};
|
|
316
|
+
return originalOn(event, wrappedListener);
|
|
317
|
+
}
|
|
318
|
+
if (event === 'end') {
|
|
319
|
+
const wrappedListener = (...args) => {
|
|
320
|
+
// Log response
|
|
321
|
+
try {
|
|
322
|
+
logger_1.Logger.log({
|
|
323
|
+
timestamp: new Date().toISOString(),
|
|
324
|
+
method: `${method} RESPONSE`,
|
|
325
|
+
url: `${url} [${res.statusCode || 0}]`,
|
|
326
|
+
headers: responseHeaders,
|
|
327
|
+
body: responseBody || undefined,
|
|
328
|
+
});
|
|
329
|
+
// Emit to DevTools (Global Bus)
|
|
330
|
+
if (startTime) {
|
|
331
|
+
event_bus_1.eventBus.emit('network:event', {
|
|
332
|
+
id: crypto.randomUUID(),
|
|
333
|
+
timestamp: startTime,
|
|
334
|
+
method,
|
|
335
|
+
url,
|
|
336
|
+
requestHeaders: requestHeaders || {},
|
|
337
|
+
requestBody: requestBody || null,
|
|
338
|
+
status: res.statusCode || 0,
|
|
339
|
+
responseHeaders: responseHeaders,
|
|
340
|
+
responseBody: responseBody || null,
|
|
341
|
+
duration: Date.now() - startTime
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
// Don't crash if logging fails
|
|
347
|
+
console.error('[serverreq] Failed to log response:', error);
|
|
348
|
+
}
|
|
349
|
+
listener(...args);
|
|
350
|
+
};
|
|
351
|
+
return originalOn(event, wrappedListener);
|
|
352
|
+
}
|
|
353
|
+
return originalOn(event, listener);
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Builds full URL from request options
|
|
358
|
+
*/
|
|
359
|
+
function buildUrl(opts, defaultProtocol) {
|
|
360
|
+
const protocol = opts.protocol || defaultProtocol;
|
|
361
|
+
const hostname = opts.hostname || opts.host || 'localhost';
|
|
362
|
+
const port = opts.port ? `:${opts.port}` : '';
|
|
363
|
+
const path = opts.path || '/';
|
|
364
|
+
return `${protocol}//${hostname}${port}${path}`;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Installs the HTTP/HTTPS interceptor
|
|
368
|
+
*/
|
|
369
|
+
function install() {
|
|
370
|
+
if (isInstalled) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const config = (0, config_1.getConfig)();
|
|
374
|
+
if (!config.get().enabled) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
patchFetch();
|
|
378
|
+
patchHttpRequest();
|
|
379
|
+
patchHttpsRequest();
|
|
380
|
+
// DevTools server is now handled via SSE in Next.js API Routes.
|
|
381
|
+
// No standalone server needed.
|
|
382
|
+
isInstalled = true;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Uninstalls the HTTP/HTTPS interceptor and restores original implementations
|
|
386
|
+
*/
|
|
387
|
+
function uninstall() {
|
|
388
|
+
if (!isInstalled) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (originalFetch) {
|
|
392
|
+
globalThis.fetch = originalFetch;
|
|
393
|
+
}
|
|
394
|
+
if (originalHttpRequest) {
|
|
395
|
+
const http = require('http');
|
|
396
|
+
http.request = originalHttpRequest;
|
|
397
|
+
}
|
|
398
|
+
if (originalHttpsRequest) {
|
|
399
|
+
const https = require('https');
|
|
400
|
+
https.request = originalHttpsRequest;
|
|
401
|
+
}
|
|
402
|
+
isInstalled = false;
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../src/interceptor.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface RequestMetadata {
|
|
2
|
+
timestamp: string;
|
|
3
|
+
method: string;
|
|
4
|
+
url: string;
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
body?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class Logger {
|
|
9
|
+
private static hasColorSupport;
|
|
10
|
+
private static color;
|
|
11
|
+
private static gray;
|
|
12
|
+
private static cyan;
|
|
13
|
+
private static yellow;
|
|
14
|
+
private static red;
|
|
15
|
+
private static maskHeaders;
|
|
16
|
+
private static maskBody;
|
|
17
|
+
private static maskObjectRecursive;
|
|
18
|
+
private static truncateBody;
|
|
19
|
+
static log(metadata: RequestMetadata): void;
|
|
20
|
+
private static logJson;
|
|
21
|
+
private static logPretty;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,MAAM;IACf,OAAO,CAAC,MAAM,CAAC,eAAe;IAI9B,OAAO,CAAC,MAAM,CAAC,KAAK;IAKpB,OAAO,CAAC,MAAM,CAAC,IAAI;IAInB,OAAO,CAAC,MAAM,CAAC,IAAI;IAInB,OAAO,CAAC,MAAM,CAAC,MAAM;IAIrB,OAAO,CAAC,MAAM,CAAC,GAAG;IAIlB,OAAO,CAAC,MAAM,CAAC,WAAW;IAW1B,OAAO,CAAC,MAAM,CAAC,QAAQ;IAcvB,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAqBlC,OAAO,CAAC,MAAM,CAAC,YAAY;IAO3B,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI;IAY3C,OAAO,CAAC,MAAM,CAAC,OAAO;IAUtB,OAAO,CAAC,MAAM,CAAC,SAAS;CA+B3B"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
const config_1 = require("./config");
|
|
5
|
+
const REDACTED = '[REDACTED]';
|
|
6
|
+
class Logger {
|
|
7
|
+
static hasColorSupport() {
|
|
8
|
+
return process.stderr.isTTY ?? false;
|
|
9
|
+
}
|
|
10
|
+
static color(text, colorCode) {
|
|
11
|
+
if (!Logger.hasColorSupport())
|
|
12
|
+
return text;
|
|
13
|
+
return `\x1b[${colorCode}m${text}\x1b[0m`;
|
|
14
|
+
}
|
|
15
|
+
static gray(text) {
|
|
16
|
+
return Logger.color(text, 90);
|
|
17
|
+
}
|
|
18
|
+
static cyan(text) {
|
|
19
|
+
return Logger.color(text, 36);
|
|
20
|
+
}
|
|
21
|
+
static yellow(text) {
|
|
22
|
+
return Logger.color(text, 33);
|
|
23
|
+
}
|
|
24
|
+
static red(text) {
|
|
25
|
+
return Logger.color(text, 31);
|
|
26
|
+
}
|
|
27
|
+
static maskHeaders(headers) {
|
|
28
|
+
const config = (0, config_1.getConfig)();
|
|
29
|
+
if (!config.get().maskSecrets)
|
|
30
|
+
return headers;
|
|
31
|
+
const masked = {};
|
|
32
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
33
|
+
masked[key] = config.isSecretHeader(key) ? REDACTED : value;
|
|
34
|
+
}
|
|
35
|
+
return masked;
|
|
36
|
+
}
|
|
37
|
+
static maskBody(body) {
|
|
38
|
+
const config = (0, config_1.getConfig)();
|
|
39
|
+
if (!config.get().maskSecrets)
|
|
40
|
+
return body;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(body);
|
|
43
|
+
const masked = Logger.maskObjectRecursive(parsed);
|
|
44
|
+
return JSON.stringify(masked);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Not JSON, return as-is
|
|
48
|
+
return body;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static maskObjectRecursive(obj) {
|
|
52
|
+
const config = (0, config_1.getConfig)();
|
|
53
|
+
if (obj === null || typeof obj !== 'object')
|
|
54
|
+
return obj;
|
|
55
|
+
if (Array.isArray(obj)) {
|
|
56
|
+
return obj.map((item) => Logger.maskObjectRecursive(item));
|
|
57
|
+
}
|
|
58
|
+
const masked = {};
|
|
59
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
60
|
+
if (config.isSecretKey(key)) {
|
|
61
|
+
masked[key] = REDACTED;
|
|
62
|
+
}
|
|
63
|
+
else if (typeof value === 'object') {
|
|
64
|
+
masked[key] = Logger.maskObjectRecursive(value);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
masked[key] = value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return masked;
|
|
71
|
+
}
|
|
72
|
+
static truncateBody(body) {
|
|
73
|
+
const config = (0, config_1.getConfig)();
|
|
74
|
+
const maxLength = config.get().maxBodyLength;
|
|
75
|
+
if (body.length <= maxLength)
|
|
76
|
+
return body;
|
|
77
|
+
return body.substring(0, maxLength) + '... [truncated]';
|
|
78
|
+
}
|
|
79
|
+
static log(metadata) {
|
|
80
|
+
const config = (0, config_1.getConfig)();
|
|
81
|
+
if (!config.shouldLogRequest(metadata.url))
|
|
82
|
+
return;
|
|
83
|
+
const format = config.get().format;
|
|
84
|
+
if (format === 'json') {
|
|
85
|
+
Logger.logJson(metadata);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
Logger.logPretty(metadata);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
static logJson(metadata) {
|
|
92
|
+
const masked = {
|
|
93
|
+
...metadata,
|
|
94
|
+
headers: Logger.maskHeaders(metadata.headers),
|
|
95
|
+
body: metadata.body ? Logger.maskBody(Logger.truncateBody(metadata.body)) : undefined,
|
|
96
|
+
};
|
|
97
|
+
process.stderr.write(JSON.stringify(masked) + '\n');
|
|
98
|
+
}
|
|
99
|
+
static logPretty(metadata) {
|
|
100
|
+
const { timestamp, method, url, headers, body } = metadata;
|
|
101
|
+
const maskedHeaders = Logger.maskHeaders(headers);
|
|
102
|
+
const maskedBody = body ? Logger.maskBody(Logger.truncateBody(body)) : undefined;
|
|
103
|
+
const lines = [];
|
|
104
|
+
// Request line
|
|
105
|
+
lines.push(`${Logger.gray(`[${timestamp}]`)} ${Logger.yellow(method)} ${Logger.cyan(url)}`);
|
|
106
|
+
// Headers
|
|
107
|
+
const headerEntries = Object.entries(maskedHeaders);
|
|
108
|
+
if (headerEntries.length > 0) {
|
|
109
|
+
lines.push(Logger.gray(' Headers:'));
|
|
110
|
+
for (const [key, value] of headerEntries) {
|
|
111
|
+
lines.push(Logger.gray(` ${key}: ${value}`));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Body
|
|
115
|
+
if (maskedBody) {
|
|
116
|
+
lines.push(Logger.gray(' Body: ') + maskedBody);
|
|
117
|
+
}
|
|
118
|
+
lines.push(''); // Empty line for spacing
|
|
119
|
+
process.stderr.write(lines.join('\n'));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.Logger = Logger;
|
|
123
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/nextjs.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Integration Helper for serverreq DevTools
|
|
3
|
+
*
|
|
4
|
+
* This module provides helpers for integrating serverreq with Next.js.
|
|
5
|
+
* Since Next.js doesn't expose its HTTP server directly, we use the
|
|
6
|
+
* standalone DevTools server approach which works reliably with Turbopack.
|
|
7
|
+
*
|
|
8
|
+
* USAGE IN next.config.js:
|
|
9
|
+
* ```js
|
|
10
|
+
* // next.config.js
|
|
11
|
+
* module.exports = {
|
|
12
|
+
* experimental: {
|
|
13
|
+
* instrumentationHook: true
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* USAGE IN instrumentation.ts:
|
|
19
|
+
* ```ts
|
|
20
|
+
* export async function register() {
|
|
21
|
+
* if (process.env.NODE_ENV === 'development') {
|
|
22
|
+
* const { setupDevTools } = await import('serverreq/nextjs');
|
|
23
|
+
* await setupDevTools();
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { install } from './interceptor';
|
|
29
|
+
export interface SetupOptions {
|
|
30
|
+
/** Port for standalone DevTools server (default: 4000) */
|
|
31
|
+
port?: number;
|
|
32
|
+
/** Whether to install HTTP interceptors (default: true) */
|
|
33
|
+
installInterceptor?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Setup DevTools for Next.js
|
|
37
|
+
* Called from instrumentation.ts
|
|
38
|
+
*/
|
|
39
|
+
export declare function setupDevTools(options?: SetupOptions): Promise<void>;
|
|
40
|
+
export { install };
|
|
41
|
+
export { eventBus } from './devtools/event-bus';
|
|
42
|
+
export { createSSEHandler } from './devtools/sse-handler';
|
|
43
|
+
//# sourceMappingURL=nextjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,WAAW,YAAY;IACzB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAc7E;AAGD,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|