refactor: eliminate all catch(err: any) with proper unknown typing + type email transport
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 19m10s
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 19m10s
- Replace all catch(err: any) with catch(err: unknown) across 8 source files - Add errorMessage() and errorCode() helpers for safe error property access - Type nodemailer transport config as SMTPTransport.Options (was any) - Type health endpoint databaseStatus (was any) - Type convert route margin param (was any) - Change queryWithRetry params from any[] to unknown[] - Update isTransientError to require Error instances (was accepting plain objects) - 19 new TDD tests (error-type-safety.test.ts) - Updated existing tests to use proper Error instances - 598 tests total, all passing, zero type errors
This commit is contained in:
parent
da049b77e3
commit
5a7ee79316
12 changed files with 221 additions and 98 deletions
|
|
@ -1,11 +1,18 @@
|
|||
import { describe, it, expect } from "vitest";
|
||||
import { isTransientError } from "../utils/errors.js";
|
||||
|
||||
/** Create an Error with a `.code` property (like Node/pg errors) */
|
||||
function makeError(opts: { code?: string; message?: string }): Error {
|
||||
const err = new Error(opts.message || "");
|
||||
if (opts.code) (err as Error & { code: string }).code = opts.code;
|
||||
return err;
|
||||
}
|
||||
|
||||
describe("isTransientError", () => {
|
||||
describe("transient error codes", () => {
|
||||
for (const code of ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT", "CONNECTION_LOST", "57P01", "57P02", "57P03", "08006", "08003", "08001"]) {
|
||||
it(`detects code ${code}`, () => {
|
||||
expect(isTransientError({ code })).toBe(true);
|
||||
expect(isTransientError(makeError({ code }))).toBe(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -20,7 +27,7 @@ describe("isTransientError", () => {
|
|||
|
||||
describe("non-transient errors", () => {
|
||||
it("rejects generic error", () => expect(isTransientError(new Error("something broke"))).toBe(false));
|
||||
it("rejects SQL syntax error", () => expect(isTransientError({ code: "42601", message: "syntax error" })).toBe(false));
|
||||
it("rejects SQL syntax error", () => expect(isTransientError(makeError({ code: "42601", message: "syntax error" }))).toBe(false));
|
||||
});
|
||||
|
||||
describe("null/undefined input", () => {
|
||||
|
|
@ -29,8 +36,9 @@ describe("isTransientError", () => {
|
|||
});
|
||||
|
||||
describe("partial error objects", () => {
|
||||
it("handles error with code but no message", () => expect(isTransientError({ code: "ECONNRESET" })).toBe(true));
|
||||
it("handles error with message but no code", () => expect(isTransientError({ message: "connection terminated" })).toBe(true));
|
||||
it("rejects error with unrelated code and no message", () => expect(isTransientError({ code: "UNKNOWN" })).toBe(false));
|
||||
it("handles Error with code but no message", () => expect(isTransientError(makeError({ code: "ECONNRESET" }))).toBe(true));
|
||||
it("handles Error with message but no code", () => expect(isTransientError(new Error("connection terminated"))).toBe(true));
|
||||
it("rejects Error with unrelated code and no message", () => expect(isTransientError(makeError({ code: "UNKNOWN" }))).toBe(false));
|
||||
it("rejects plain object (not an Error instance)", () => expect(isTransientError({ code: "ECONNRESET" })).toBe(false));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue