fix(cli): Remove unsafe type assertions in activityLogger #19713 (#19745)

This commit is contained in:
nityam
2026-02-24 09:24:09 +05:30
committed by GitHub
parent dde844dbe1
commit ee5eb70070
+130 -26
View File
@@ -22,13 +22,82 @@ import WebSocket from 'ws';
const ACTIVITY_ID_HEADER = 'x-activity-request-id'; const ACTIVITY_ID_HEADER = 'x-activity-request-id';
const MAX_BUFFER_SIZE = 100; const MAX_BUFFER_SIZE = 100;
/** Type guard: Array.isArray doesn't narrow readonly arrays in TS 5.8 */
function isHeaderRecord( function isHeaderRecord(
h: http.OutgoingHttpHeaders | readonly string[], h: http.OutgoingHttpHeaders | readonly string[],
): h is http.OutgoingHttpHeaders { ): h is http.OutgoingHttpHeaders {
return !Array.isArray(h); return !Array.isArray(h);
} }
function isRequestOptions(value: unknown): value is http.RequestOptions {
return (
typeof value === 'object' &&
value !== null &&
!(value instanceof URL) &&
!Array.isArray(value)
);
}
function isIncomingMessageCallback(
value: unknown,
): value is (res: http.IncomingMessage) => void {
return typeof value === 'function';
}
type HttpRequestArgs =
| []
| [
url: string | URL | http.RequestOptions,
options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
callback?: (res: http.IncomingMessage) => void,
];
function callHttpRequest(
originalFn: typeof http.request,
args: HttpRequestArgs,
): http.ClientRequest {
if (args.length === 0) {
return originalFn({});
}
if (args.length === 1) {
const first = args[0];
if (typeof first === 'string' || first instanceof URL) {
return originalFn(first);
}
if (isRequestOptions(first)) {
return originalFn(first);
}
return originalFn({});
}
if (args.length === 2) {
const first = args[0];
const second = args[1];
if (typeof first === 'string' || first instanceof URL) {
if (isIncomingMessageCallback(second)) {
return originalFn(first, second);
}
if (isRequestOptions(second)) {
return originalFn(first, second);
}
}
if (isRequestOptions(first) && isIncomingMessageCallback(second)) {
return originalFn(first, second);
}
}
if (args.length === 3) {
const first = args[0];
const second = args[1];
const third = args[2];
if (
(typeof first === 'string' || first instanceof URL) &&
isRequestOptions(second) &&
isIncomingMessageCallback(third)
) {
return originalFn(first, second, third);
}
}
return originalFn({});
}
export interface NetworkLog { export interface NetworkLog {
id: string; id: string;
timestamp: number; timestamp: number;
@@ -364,7 +433,7 @@ export class ActivityLogger extends EventEmitter {
const wrapRequest = ( const wrapRequest = (
originalFn: typeof http.request, originalFn: typeof http.request,
args: unknown[], args: HttpRequestArgs,
protocol: string, protocol: string,
) => { ) => {
const firstArg = args[0]; const firstArg = args[0];
@@ -373,8 +442,10 @@ export class ActivityLogger extends EventEmitter {
options = firstArg; options = firstArg;
} else if (firstArg instanceof URL) { } else if (firstArg instanceof URL) {
options = firstArg; options = firstArg;
} else if (firstArg && typeof firstArg === 'object') {
options = isRequestOptions(firstArg) ? firstArg : {};
} else { } else {
options = (firstArg ?? {}) as http.RequestOptions; options = {};
} }
let url = ''; let url = '';
@@ -393,9 +464,9 @@ export class ActivityLogger extends EventEmitter {
`${protocol}//${options.hostname || options.host || 'localhost'}${options.path || '/'}`; `${protocol}//${options.hostname || options.host || 'localhost'}${options.path || '/'}`;
} }
if (url.includes('127.0.0.1') || url.includes('localhost')) if (url.includes('127.0.0.1') || url.includes('localhost')) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion return callHttpRequest(originalFn, args);
return originalFn.apply(http, args as any); }
const rawHeaders = const rawHeaders =
typeof options === 'object' && typeof options === 'object' &&
@@ -410,24 +481,23 @@ export class ActivityLogger extends EventEmitter {
if (headers[ACTIVITY_ID_HEADER]) { if (headers[ACTIVITY_ID_HEADER]) {
delete headers[ACTIVITY_ID_HEADER]; delete headers[ACTIVITY_ID_HEADER];
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion return callHttpRequest(originalFn, args);
return originalFn.apply(http, args as any);
} }
const id = Math.random().toString(36).substring(7); const id = Math.random().toString(36).substring(7);
this.requestStartTimes.set(id, Date.now()); this.requestStartTimes.set(id, Date.now());
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion const req = callHttpRequest(originalFn, args);
const req = originalFn.apply(http, args as any);
const requestChunks: Buffer[] = []; const requestChunks: Buffer[] = [];
const oldWrite = req.write; const oldWrite = req.write;
const oldEnd = req.end; const oldEnd = req.end;
req.write = function (chunk: unknown, ...etc: unknown[]) { req.write = function (chunk: string | Uint8Array, ...etc: unknown[]) {
if (chunk) { if (chunk) {
const encoding = const encoding =
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
typeof etc[0] === 'string' ? (etc[0] as BufferEncoding) : undefined; ? etc[0]
: undefined;
requestChunks.push( requestChunks.push(
Buffer.isBuffer(chunk) Buffer.isBuffer(chunk)
? chunk ? chunk
@@ -438,19 +508,21 @@ export class ActivityLogger extends EventEmitter {
), ),
); );
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return
return oldWrite.apply(this, [chunk, ...etc] as any); return (oldWrite as any).apply(this, [chunk, ...etc]);
}; };
req.end = function ( req.end = function (
this: http.ClientRequest, this: http.ClientRequest,
chunk: unknown, chunkOrCb?: string | Uint8Array | (() => void),
...etc: unknown[] ...etc: unknown[]
) { ) {
if (chunk && typeof chunk !== 'function') { const chunk = typeof chunkOrCb === 'function' ? undefined : chunkOrCb;
if (chunk) {
const encoding = const encoding =
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
typeof etc[0] === 'string' ? (etc[0] as BufferEncoding) : undefined; ? etc[0]
: undefined;
requestChunks.push( requestChunks.push(
Buffer.isBuffer(chunk) Buffer.isBuffer(chunk)
? chunk ? chunk
@@ -473,7 +545,7 @@ export class ActivityLogger extends EventEmitter {
pending: true, pending: true,
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return
return (oldEnd as any).apply(this, [chunk, ...etc]); return (oldEnd as any).apply(this, [chunkOrCb, ...etc]);
}; };
req.on('response', (res: http.IncomingMessage) => { req.on('response', (res: http.IncomingMessage) => {
@@ -545,12 +617,44 @@ export class ActivityLogger extends EventEmitter {
return req; return req;
}; };
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion Object.defineProperty(http, 'request', {
(http as any).request = (...args: unknown[]) => value: (
wrapRequest(originalRequest, args, 'http:'); url: string | URL | http.RequestOptions,
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
(https as any).request = (...args: unknown[]) => callback?: (res: http.IncomingMessage) => void,
wrapRequest(originalHttpsRequest as typeof http.request, args, 'https:'); ): http.ClientRequest => {
const args: HttpRequestArgs =
callback !== undefined
? [url, options, callback]
: options !== undefined
? [url, options]
: [url];
return wrapRequest(originalRequest, args, 'http:');
},
writable: true,
configurable: true,
});
Object.defineProperty(https, 'request', {
value: (
url: string | URL | http.RequestOptions,
options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
callback?: (res: http.IncomingMessage) => void,
): http.ClientRequest => {
const args: HttpRequestArgs =
callback !== undefined
? [url, options, callback]
: options !== undefined
? [url, options]
: [url];
return wrapRequest(
originalHttpsRequest as typeof http.request,
args,
'https:',
);
},
writable: true,
configurable: true,
});
} }
logConsole(payload: ConsoleLogPayload) { logConsole(payload: ConsoleLogPayload) {