fix: make linting required for CI (#27091)
* fix: make linting required for CI - Remove continue-on-error from lint workflow so CI fails on lint errors - Fix 2 lint errors: avoid importing from @trpc/server in lib package - Add trpcErrorUtils.ts to handle TRPC errors without circular dependencies - Update lint-staged to show warnings but not block commits Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: add message field validation to isTRPCErrorLike type guard Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Volnei Munhoz
Devin AI
parent
f17933bc43
commit
ddcac4b3b1
@@ -16,4 +16,3 @@ jobs:
|
||||
- uses: ./.github/actions/yarn-install
|
||||
- name: Run Lint
|
||||
run: yarn lint
|
||||
continue-on-error: true
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
const skipWarnings = ["1", "true", "yes", "on"].includes(
|
||||
(process.env.SKIP_WARNINGS ?? "").toLowerCase()
|
||||
);
|
||||
|
||||
export default {
|
||||
"(apps|packages|companion)/**/*.{js,ts,jsx,tsx}": (files) =>
|
||||
skipWarnings
|
||||
? `biome lint --config-path=biome-staged.json ${files.join(" ")}`
|
||||
: `biome lint --config-path=biome-staged.json --error-on-warnings ${files.join(" ")}`,
|
||||
`biome lint --config-path=biome-staged.json ${files.join(" ")}`,
|
||||
"packages/prisma/schema.prisma": ["prisma format"],
|
||||
};
|
||||
|
||||
@@ -3,10 +3,19 @@ import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { defaultResponder } from "./defaultResponder";
|
||||
|
||||
/**
|
||||
* Creates a mock TRPC-like error for testing purposes.
|
||||
* This avoids importing from @trpc/server in the lib package.
|
||||
*/
|
||||
function createMockTRPCError(code: string): Error {
|
||||
const error = new Error(`TRPC Error: ${code}`);
|
||||
error.name = "TRPCError";
|
||||
(error as Error & { code: string }).code = code;
|
||||
return error;
|
||||
}
|
||||
|
||||
describe("defaultResponder", () => {
|
||||
it("should call res.json when response is still writable and result is not null", async () => {
|
||||
const f = vi.fn().mockResolvedValue({});
|
||||
@@ -43,7 +52,7 @@ describe("defaultResponder", () => {
|
||||
expect(res.status).toHaveBeenCalledWith(409);
|
||||
});
|
||||
it("Rate limit should respond with a 429 status code", async () => {
|
||||
const f = vi.fn().mockRejectedValue(new TRPCError({ code: "TOO_MANY_REQUESTS" }));
|
||||
const f = vi.fn().mockRejectedValue(createMockTRPCError("TOO_MANY_REQUESTS"));
|
||||
const req = {} as NextApiRequest;
|
||||
const res = {
|
||||
status: vi.fn().mockReturnThis(),
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
|
||||
|
||||
import { type TraceContext } from "@calcom/lib/tracing";
|
||||
import { TracedError } from "@calcom/lib/tracing/error";
|
||||
import { distributedTracing } from "@calcom/lib/tracing/factory";
|
||||
@@ -11,6 +8,7 @@ import { HttpError } from "../http-error";
|
||||
import { safeStringify } from "../safeStringify";
|
||||
import { getServerErrorFromUnknown } from "./getServerErrorFromUnknown";
|
||||
import { performance } from "./perfObserver";
|
||||
import { getHTTPStatusCodeFromTRPCErrorLike, isTRPCErrorLike } from "./trpcErrorUtils";
|
||||
|
||||
export interface TracedRequest extends NextApiRequest {
|
||||
traceContext: TraceContext;
|
||||
@@ -58,8 +56,8 @@ export function defaultResponder<T>(
|
||||
tracingLogger.error(`${operation} request failed`, safeStringify(err));
|
||||
const tracedError = TracedError.createFromError(err, traceContext);
|
||||
let error: HttpError;
|
||||
if (err instanceof TRPCError) {
|
||||
const statusCode = getHTTPStatusCodeFromError(err);
|
||||
if (isTRPCErrorLike(err)) {
|
||||
const statusCode = getHTTPStatusCodeFromTRPCErrorLike(err);
|
||||
error = new HttpError({ statusCode, message: err.message });
|
||||
} else {
|
||||
error = getServerErrorFromUnknown(tracedError);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Utility functions for handling TRPC-like errors without importing from @trpc/server.
|
||||
* This avoids circular dependencies in the lib package.
|
||||
*/
|
||||
|
||||
const TRPC_ERROR_CODES_TO_HTTP: Record<string, number> = {
|
||||
PARSE_ERROR: 400,
|
||||
BAD_REQUEST: 400,
|
||||
UNAUTHORIZED: 401,
|
||||
NOT_FOUND: 404,
|
||||
FORBIDDEN: 403,
|
||||
METHOD_NOT_SUPPORTED: 405,
|
||||
TIMEOUT: 408,
|
||||
CONFLICT: 409,
|
||||
PRECONDITION_FAILED: 412,
|
||||
PAYLOAD_TOO_LARGE: 413,
|
||||
UNPROCESSABLE_CONTENT: 422,
|
||||
TOO_MANY_REQUESTS: 429,
|
||||
CLIENT_CLOSED_REQUEST: 499,
|
||||
INTERNAL_SERVER_ERROR: 500,
|
||||
NOT_IMPLEMENTED: 501,
|
||||
BAD_GATEWAY: 502,
|
||||
SERVICE_UNAVAILABLE: 503,
|
||||
GATEWAY_TIMEOUT: 504,
|
||||
};
|
||||
|
||||
interface TRPCErrorLike {
|
||||
name: string;
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function isTRPCErrorLike(err: unknown): err is TRPCErrorLike {
|
||||
return (
|
||||
err !== null &&
|
||||
typeof err === "object" &&
|
||||
"name" in err &&
|
||||
err.name === "TRPCError" &&
|
||||
"code" in err &&
|
||||
typeof (err as TRPCErrorLike).code === "string" &&
|
||||
"message" in err &&
|
||||
typeof (err as TRPCErrorLike).message === "string"
|
||||
);
|
||||
}
|
||||
|
||||
export function getHTTPStatusCodeFromTRPCErrorLike(err: TRPCErrorLike): number {
|
||||
return TRPC_ERROR_CODES_TO_HTTP[err.code] ?? 500;
|
||||
}
|
||||
Reference in New Issue
Block a user