From 3b752f9d4cbb79a7db3a444e3d3da75cef9b9bcf Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Sat, 29 Aug 2026 03:06:50 -0300 Subject: [PATCH] chore(quality): type the 55 no-explicit-any sites frozen under #11924 (#11975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Production (open-sse/utils/socksConnectorWithFamily.ts, 4 sites): every cast was redundant — undici's buildConnector.BuildOptions already has `timeout?: number | null`, socks' SocksClientOptions has `timeout?: number`, and Agent.Options' `connect` / `connectTimeout` narrow to the connector's parameter types on their own. Behaviour unchanged; check:open-sse-typecheck stays at the frozen 5. Tests (51 sites): the socks-timeout mocks now carry the real types — the patched SocksClient.createConnection is typed as the static it replaces, the fake buildConnector returns buildConnector.connector, the proxy is a SocksProxy, the dynamic import is typed as the module it loads; the e2e suite passes a SocksProxy and Agent.Options and no longer casts undici's fetch init (its RequestInit already has `dispatcher`); the isFree suites narrow getCustomModels()' JSON to a declared row shape, feed deliberately-wrong values through `unknown`, and stop casting for zod's safeParse, which takes unknown. The six files' suppression entries are removed: 1238 → 1232 files, 5487 → 5432 suppressed. ESLint without the suppressions file reports 0 problems on all six; with it, no stale entry is left. The five suites pass (4, 2, 5, 4, 4). --- .../maintenance/11924-type-the-frozen-any.md | 1 + config/quality/eslint-suppressions.json | 32 +------- open-sse/utils/socksConnectorWithFamily.ts | 10 ++- tests/unit/free-models-isfree.test.ts | 9 ++- tests/unit/models-db-isfree.test.ts | 38 ++++----- ...providerModelMutationSchema-isfree.test.ts | 32 ++++++-- tests/unit/socks-connect-timeout-e2e.test.ts | 44 +++++++--- tests/unit/socks-connect-timeout.test.ts | 80 ++++++++++++++----- 8 files changed, 154 insertions(+), 92 deletions(-) create mode 100644 changelog.d/maintenance/11924-type-the-frozen-any.md diff --git a/changelog.d/maintenance/11924-type-the-frozen-any.md b/changelog.d/maintenance/11924-type-the-frozen-any.md new file mode 100644 index 0000000000..62267560f7 --- /dev/null +++ b/changelog.d/maintenance/11924-type-the-frozen-any.md @@ -0,0 +1 @@ +- Type the 55 `no-explicit-any` sites that had been frozen under #11924 — four redundant casts in `socksConnectorWithFamily.ts` (undici/socks types already accept them) and the mocks/fixtures of the socks-timeout and isFree suites — and drop their suppression entries; the ESLint ratchet shrinks from 5487 to 5432 (Closes #11924) diff --git a/config/quality/eslint-suppressions.json b/config/quality/eslint-suppressions.json index f31734f5e4..ad571e9e24 100644 --- a/config/quality/eslint-suppressions.json +++ b/config/quality/eslint-suppressions.json @@ -837,11 +837,6 @@ "count": 5 } }, - "open-sse/utils/socksConnectorWithFamily.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 4 - } - }, "open-sse/utils/stream.ts": { "@typescript-eslint/no-unused-vars": { "count": 2 @@ -4952,11 +4947,6 @@ "count": 20 } }, - "tests/unit/free-models-isfree.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 2 - } - }, "tests/unit/functional-gateway-mirrors-append.test.ts": { "@typescript-eslint/no-unused-vars": { "count": 1 @@ -5243,11 +5233,6 @@ "count": 3 } }, - "tests/unit/models-db-isfree.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 18 - } - }, "tests/unit/modelsDevSync-extended.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 2 @@ -5547,11 +5532,6 @@ "count": 4 } }, - "tests/unit/providerModelMutationSchema-isfree.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 2 - } - }, "tests/unit/providers-route-managed-catalog.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 4 @@ -6021,16 +6001,6 @@ "count": 7 } }, - "tests/unit/socks-connect-timeout-e2e.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 11 - } - }, - "tests/unit/socks-connect-timeout.test.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 18 - } - }, "tests/unit/spend-batch-writer.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -6552,4 +6522,4 @@ "count": 2 } } -} \ No newline at end of file +} diff --git a/open-sse/utils/socksConnectorWithFamily.ts b/open-sse/utils/socksConnectorWithFamily.ts index adda58590f..5e9fb0c4fa 100644 --- a/open-sse/utils/socksConnectorWithFamily.ts +++ b/open-sse/utils/socksConnectorWithFamily.ts @@ -49,13 +49,15 @@ export function socksConnectorWithFamily( const isDisabled = connectTimeout === 0; // SOCKS lib: 0 throws (isValidTimeoutValue: value>0) and undefined → DEFAULT_TIMEOUT 30s; // undici: 0 disables (core/util.js: if (!opts.timeout) return noop), undefined → 10s. Divergence intentional. - const handshakeTimeout = isDisabled ? undefined : (connectTimeout ?? resolveSocksHandshakeTimeoutMs()); + const handshakeTimeout = isDisabled + ? undefined + : (connectTimeout ?? resolveSocksHandshakeTimeoutMs()); const tlsTimeout = connectTimeout; // Sequential budget: both phases bounded by the same connectTimeout → wall-time up to 60s for https // (vs 30s direct). Shared-deadline alternative rejected as unjustified complexity. const build = _buildConnectorForTest ?? buildConnector; const undiciConnect = build( - tlsTimeout !== undefined ? ({ ...tlsOpts, timeout: tlsTimeout } as any) : tlsOpts + tlsTimeout !== undefined ? { ...tlsOpts, timeout: tlsTimeout } : tlsOpts ); const socketOptions = buildSocksFamilySocketOptions(family); return async (options, callback) => { @@ -69,7 +71,7 @@ export function socksConnectorWithFamily( const r = await SocksClient.createConnection({ command: "connect", proxy, - timeout: handshakeTimeout as any, + timeout: handshakeTimeout, destination: { host: hostname, port: resolvePort(protocol, port) }, existing_socket: httpSocket as never, socket_options: socketOptions as never, @@ -97,6 +99,6 @@ export function createSocksDispatcherWithFamily( }; return new Agent({ ...rest, - connect: socksConnectorWithFamily(proxy, family, connect as any, connectTimeout as any), + connect: socksConnectorWithFamily(proxy, family, connect, connectTimeout), }); } diff --git a/tests/unit/free-models-isfree.test.ts b/tests/unit/free-models-isfree.test.ts index 7657a69c92..53217ace47 100644 --- a/tests/unit/free-models-isfree.test.ts +++ b/tests/unit/free-models-isfree.test.ts @@ -9,8 +9,13 @@ describe("isFreeModel isFree opt-in", () => { assert.equal(isFreeModel("local", { id: "my-model", isFree: true }), true); }); it("isFree:false/null/undefined/1/'true' → not free (strict ===true)", () => { - for (const v of [false, null, undefined, 1, "true" as any]) { - assert.equal(isFreeModel("any", { id: "x", isFree: v as any }), false, `isFree=${String(v)} should be false`); + const junk: unknown[] = [false, null, undefined, 1, "true"]; + for (const v of junk) { + assert.equal( + isFreeModel("any", { id: "x", isFree: v as boolean }), + false, + `isFree=${String(v)} should be false` + ); } }); it("providerHasFreeModels unchanged by custom isFree", () => { diff --git a/tests/unit/models-db-isfree.test.ts b/tests/unit/models-db-isfree.test.ts index df2e23485d..77e296157b 100644 --- a/tests/unit/models-db-isfree.test.ts +++ b/tests/unit/models-db-isfree.test.ts @@ -11,6 +11,8 @@ import { rmSync, mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; +type CustomRow = { id: string; isFree?: boolean }; + describe("custom isFree tri-state (DB)", () => { let dir: string; let prevDataDir: string | undefined; @@ -44,8 +46,8 @@ describe("custom isFree tri-state (DB)", () => { undefined, true ); - const rows: any = await getCustomModels("p"); - const r = rows.find((x: any) => x.id === "m1"); + const rows = (await getCustomModels("p")) as CustomRow[]; + const r = rows.find((x) => x.id === "m1"); assert.equal(r.isFree, true); await addCustomModel( "p", @@ -60,8 +62,8 @@ describe("custom isFree tri-state (DB)", () => { undefined, undefined ); - const rows2: any = await getCustomModels("p"); - const r2 = rows2.find((x: any) => x.id === "m2"); + const rows2 = (await getCustomModels("p")) as CustomRow[]; + const r2 = rows2.find((x) => x.id === "m2"); assert.equal(r2.isFree, undefined); }); @@ -79,9 +81,9 @@ describe("custom isFree tri-state (DB)", () => { undefined, true ); - await updateCustomModel("p", "m", { isFree: null } as any); - const rows: any = await getCustomModels("p"); - const r = rows.find((x: any) => x.id === "m"); + await updateCustomModel("p", "m", { isFree: null }); + const rows = (await getCustomModels("p")) as CustomRow[]; + const r = rows.find((x) => x.id === "m"); assert.equal(r.isFree, undefined); }); @@ -99,13 +101,13 @@ describe("custom isFree tri-state (DB)", () => { undefined, undefined ); - await updateCustomModel("p", "m", { isFree: true } as any); - let rows: any = await getCustomModels("p"); - assert.equal(rows.find((x: any) => x.id === "m").isFree, true); + await updateCustomModel("p", "m", { isFree: true }); + let rows = (await getCustomModels("p")) as CustomRow[]; + assert.equal(rows.find((x) => x.id === "m").isFree, true); // tri-state helper treats false as Boolean(false) → stored as false (falsy free), but only true is free per isFree guard - await updateCustomModel("p", "m", { isFree: false } as any); + await updateCustomModel("p", "m", { isFree: false }); rows = await getCustomModels("p"); - assert.equal(rows.find((x: any) => x.id === "m").isFree, false); + assert.equal(rows.find((x) => x.id === "m").isFree, false); }); it("replaceCustomModels preserves isFree (new wins else prev)", async () => { @@ -138,15 +140,15 @@ describe("custom isFree tri-state (DB)", () => { // replace with new truth for override, omit for keep (prev should win) await replaceCustomModels("p", [ { id: "keep", name: "keep" }, - { id: "override", name: "override", isFree: true } as any, + { id: "override", name: "override", isFree: true }, ]); - const rows: any = await getCustomModels("p"); + const rows = (await getCustomModels("p")) as CustomRow[]; assert.equal( - rows.find((x: any) => x.id === "keep").isFree, + rows.find((x) => x.id === "keep").isFree, true, "prev isFree preserved when new omits" ); - assert.equal(rows.find((x: any) => x.id === "override").isFree, true, "new isFree wins"); + assert.equal(rows.find((x) => x.id === "override").isFree, true, "new isFree wins"); }); it("allowEmpty:false intact (no destructive clear)", async () => { @@ -163,8 +165,8 @@ describe("custom isFree tri-state (DB)", () => { undefined, true ); - const before: any = await getCustomModels("p"); - const after: any = await replaceCustomModels("p", [], { allowEmpty: false }); + const before = (await getCustomModels("p")) as CustomRow[]; + const after = await replaceCustomModels("p", [], { allowEmpty: false }); assert.equal(after.length, before.length); }); }); diff --git a/tests/unit/providerModelMutationSchema-isfree.test.ts b/tests/unit/providerModelMutationSchema-isfree.test.ts index 63ee499a8d..e6eaceab11 100644 --- a/tests/unit/providerModelMutationSchema-isfree.test.ts +++ b/tests/unit/providerModelMutationSchema-isfree.test.ts @@ -4,17 +4,35 @@ import { providerModelMutationSchema } from "../../src/shared/validation/schemas describe("providerModelMutationSchema isFree", () => { it("isFree:true accepted", () => { - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: true }).success, true); + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: true }).success, + true + ); }); it("old payload without isFree still valid", () => { - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m" }).success, true); + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m" }).success, + true + ); }); - it("rejects isFree:0 and isFree:\"yes\"", () => { - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: 0 as any }).success, false); - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: "yes" as any }).success, false); + it('rejects isFree:0 and isFree:"yes"', () => { + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: 0 }).success, + false + ); + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: "yes" }).success, + false + ); }); it("nullable true/false/null accepted", () => { - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: null }).success, true); - assert.equal(providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: false }).success, true); + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: null }).success, + true + ); + assert.equal( + providerModelMutationSchema.safeParse({ provider: "p", modelId: "m", isFree: false }).success, + true + ); }); }); diff --git a/tests/unit/socks-connect-timeout-e2e.test.ts b/tests/unit/socks-connect-timeout-e2e.test.ts index 9c62d0a906..2127d76f3a 100644 --- a/tests/unit/socks-connect-timeout-e2e.test.ts +++ b/tests/unit/socks-connect-timeout-e2e.test.ts @@ -1,11 +1,14 @@ import { describe, it, afterEach } from "node:test"; import assert from "node:assert/strict"; import net from "node:net"; -import { fetch } from "undici"; +import { fetch, type Agent } from "undici"; +import type { SocksProxy } from "socks"; import { createSocksDispatcherWithFamily } from "../../open-sse/utils/socksConnectorWithFamily.ts"; import { clearDispatcherCache } from "../../open-sse/utils/proxyDispatcher.ts"; -async function startFakeSocks(opts: { stallAfterGrant: boolean }): Promise<{ port: number; close: () => Promise }> { +async function startFakeSocks(opts: { + stallAfterGrant: boolean; +}): Promise<{ port: number; close: () => Promise }> { return new Promise((resolve) => { const serverSockets = new Set(); const server = net.createServer((socket) => { @@ -44,22 +47,43 @@ describe("stub SOCKS e2e", () => { it("pre-grant stall (SOCKS timer) \u2192 error < 1000ms", async () => { const { port, close } = await startFakeSocks({ stallAfterGrant: false }); - const dispatcher = createSocksDispatcherWithFamily({ host: "127.0.0.1", port, type: 5 } as any, 4 as any, { connectTimeout: 300, connect: {} } as any); + const proxy: SocksProxy = { host: "127.0.0.1", port, type: 5 }; + const dispatcher = createSocksDispatcherWithFamily(proxy, 4, { + connectTimeout: 300, + connect: {}, + } as Agent.Options); const t0 = Date.now(); - await assert.rejects(() => fetch("https://example.invalid/", { dispatcher } as any)); - assert.ok(Date.now() - t0 < 1000, `pre-grant stall must error < 1000ms, took ${Date.now() - t0}ms`); + await assert.rejects(() => fetch("https://example.invalid/", { dispatcher })); + assert.ok( + Date.now() - t0 < 1000, + `pre-grant stall must error < 1000ms, took ${Date.now() - t0}ms` + ); await close(); }); it("post-grant stall (TLS timer, https:// only) \u2192 error < 1500ms", async () => { const { port, close } = await startFakeSocks({ stallAfterGrant: true }); - const dispatcher = createSocksDispatcherWithFamily({ host: "127.0.0.1", port, type: 5 } as any, 4 as any, { connectTimeout: 300, connect: {} } as any); + const proxy: SocksProxy = { host: "127.0.0.1", port, type: 5 }; + const dispatcher = createSocksDispatcherWithFamily(proxy, 4, { + connectTimeout: 300, + connect: {}, + } as Agent.Options); const t0 = Date.now(); - let caught: any = null; - await assert.rejects(async () => { try { await fetch("https://example.invalid/", { dispatcher } as any); } catch (e) { caught = e; throw e; } }); - const err: any = caught; + let caught: unknown = null; + await assert.rejects(async () => { + try { + await fetch("https://example.invalid/", { dispatcher }); + } catch (e) { + caught = e; + throw e; + } + }); + const err = caught as { message?: string } | null; // The ~1000ms wall time is connectTimeout 300ms + undici immediate/queue overhead, not the 10000ms default. - assert.ok(Date.now() - t0 < 1500, `post-grant stall must error < 1500ms, took ${Date.now() - t0}ms (err: ${String((err as any)?.message ?? err).slice(0, 120)})`); + assert.ok( + Date.now() - t0 < 1500, + `post-grant stall must error < 1500ms, took ${Date.now() - t0}ms (err: ${String(err?.message ?? err).slice(0, 120)})` + ); await close(); }); }); diff --git a/tests/unit/socks-connect-timeout.test.ts b/tests/unit/socks-connect-timeout.test.ts index dc54901a1d..7eee20a128 100644 --- a/tests/unit/socks-connect-timeout.test.ts +++ b/tests/unit/socks-connect-timeout.test.ts @@ -1,6 +1,8 @@ import { describe, it, afterEach, beforeEach } from "node:test"; import assert from "node:assert/strict"; -import { SocksClient } from "socks"; +import type net from "node:net"; +import { SocksClient, type SocksClientOptions, type SocksProxy } from "socks"; +import type { buildConnector } from "undici"; // Lightweight oracle — node:test, no vi.mock. // We patch SocksClient.createConnection (writable) and inject a fake @@ -8,59 +10,79 @@ import { SocksClient } from "socks"; // mutating the read-only undici module. describe("socks connectTimeout forwarder", () => { - let capturedTimeout: any = undefined; - let capturedTlsTimeout: any = undefined; + let capturedTimeout: number | undefined = undefined; + let capturedTlsTimeout: number | null | undefined = undefined; let capturedTlsUndefined = false; - let origCreateConnection: any; + let origCreateConnection: typeof SocksClient.createConnection; beforeEach(() => { origCreateConnection = SocksClient.createConnection; capturedTimeout = undefined; capturedTlsTimeout = undefined; capturedTlsUndefined = false; - (SocksClient as any).createConnection = async (opts: any) => { + SocksClient.createConnection = (async (opts: SocksClientOptions) => { capturedTimeout = opts?.timeout; - return { socket: { setNoDelay: () => ({ setNoDelay: () => {} }) } } as any; - }; + return { socket: { setNoDelay: () => ({ setNoDelay: () => {} }) } } as unknown as Awaited< + ReturnType + >; + }) as typeof SocksClient.createConnection; }); afterEach(() => { - (SocksClient as any).createConnection = origCreateConnection; + SocksClient.createConnection = origCreateConnection; capturedTimeout = undefined; capturedTlsTimeout = undefined; capturedTlsUndefined = false; }); - function fakeBuildConnector(opts: any = {}) { + function fakeBuildConnector(opts: buildConnector.BuildOptions = {}): buildConnector.connector { if (opts && typeof opts.timeout !== "undefined") capturedTlsTimeout = opts.timeout; else capturedTlsUndefined = true; - return (_options: any, cb: any) => cb(null, { setNoDelay: () => ({}) } as any); + return (_options, cb) => cb(null, { setNoDelay: () => ({}) } as unknown as net.Socket); } async function driveConnector(args: { family: 4 | 6 | null; - tlsOpts?: any; + tlsOpts?: buildConnector.BuildOptions; connectTimeout?: number; protocol?: string; hostname?: string; port?: string; }) { - const mod: any = await import(`../../open-sse/utils/socksConnectorWithFamily.ts?t=${Date.now()}-${Math.random()}`); - const proxy = { host: "1.2.3.4", port: 1080, type: 5 } as any; + const mod = (await import( + `../../open-sse/utils/socksConnectorWithFamily.ts?t=${Date.now()}-${Math.random()}` + )) as typeof import("../../open-sse/utils/socksConnectorWithFamily.ts"); + const proxy: SocksProxy = { host: "1.2.3.4", port: 1080, type: 5 }; const tlsOpts = args.tlsOpts ?? {}; const connectTimeout = args.connectTimeout; - const connector: any = mod.socksConnectorWithFamily(proxy, args.family, tlsOpts, connectTimeout, fakeBuildConnector as any); + const connector = mod.socksConnectorWithFamily( + proxy, + args.family, + tlsOpts, + connectTimeout, + fakeBuildConnector + ); await new Promise((resolve, reject) => connector( - { protocol: args.protocol ?? "https:", hostname: args.hostname ?? "example.com", port: args.port ?? "443" } as any, - (err: any) => (err ? reject(err) : resolve()) + { + protocol: args.protocol ?? "https:", + hostname: args.hostname ?? "example.com", + port: args.port ?? "443", + }, + (err) => (err ? reject(err) : resolve()) ) ); return { capturedTimeout, capturedTlsTimeout, capturedTlsUndefined, mod, connector }; } it("U1: Agent.connectTimeout → SocksClient.timeout + TLS timeout", async () => { - const { capturedTimeout: t, capturedTlsTimeout: tls } = await driveConnector({ family: 4, tlsOpts: {}, connectTimeout: 5000, protocol: "https:", port: "443" }); + const { capturedTimeout: t, capturedTlsTimeout: tls } = await driveConnector({ + family: 4, + tlsOpts: {}, + connectTimeout: 5000, + protocol: "https:", + port: "443", + }); assert.equal(t, 5000); assert.equal(tls, 5000); }); @@ -69,7 +91,13 @@ describe("socks connectTimeout forwarder", () => { const prev = process.env.SOCKS_HANDSHAKE_TIMEOUT_MS; process.env.SOCKS_HANDSHAKE_TIMEOUT_MS = "7777"; try { - const { capturedTimeout: t, capturedTlsUndefined: tlsUndef } = await driveConnector({ family: 6, tlsOpts: {}, connectTimeout: undefined, protocol: "https:", port: "443" }); + const { capturedTimeout: t, capturedTlsUndefined: tlsUndef } = await driveConnector({ + family: 6, + tlsOpts: {}, + connectTimeout: undefined, + protocol: "https:", + port: "443", + }); assert.equal(t, 7777); assert.equal(tlsUndef, true); } finally { @@ -79,12 +107,24 @@ describe("socks connectTimeout forwarder", () => { }); it("U3: http (no TLS) still bounds SocksClient", async () => { - const { capturedTimeout: t } = await driveConnector({ family: null, tlsOpts: {}, connectTimeout: 5000, protocol: "http:", port: "80" }); + const { capturedTimeout: t } = await driveConnector({ + family: null, + tlsOpts: {}, + connectTimeout: 5000, + protocol: "http:", + port: "80", + }); assert.equal(t, 5000); }); it("U4: connectTimeout=0 → SocksClient undefined (SOCKS defaults to 30s) + TLS timeout 0 (disabled)", async () => { - const { capturedTimeout: t, capturedTlsTimeout: tls } = await driveConnector({ family: 4, tlsOpts: {}, connectTimeout: 0, protocol: "https:", port: "443" }); + const { capturedTimeout: t, capturedTlsTimeout: tls } = await driveConnector({ + family: 4, + tlsOpts: {}, + connectTimeout: 0, + protocol: "https:", + port: "443", + }); assert.equal(t, undefined); assert.equal(tls, 0); });