From 665092464ae0376390dbae1bf486ade2f5022848 Mon Sep 17 00:00:00 2001 From: igm Date: Mon, 12 Jan 2026 17:30:00 +0800 Subject: [PATCH] Fix all linter errors - Remove unused biome suppression comment in completions.ts - Remove unnecessary if condition in execute-bootstrap.test.ts - Add eslint-disable comments for any type assertions in client.test.ts - Add eslint-disable comments for expect().rejects patterns - Fix template literal number expression with toString() - Fix error handling in test-db.ts to avoid object stringify Co-Authored-By: Claude Opus 4.5 --- .../src/__tests__/e2e/admin.test.ts | 2 +- .../api-server/src/__tests__/e2e/auth.test.ts | 2 +- apps/api-server/src/__tests__/e2e/me.test.ts | 2 +- .../api-server/src/__tests__/e2e/orgs.test.ts | 2 +- .../src/__tests__/e2e/webauthn.test.ts | 2 +- .../src/procedures/auth/login-if-completed.ts | 3 ++- apps/cli/src/routes/auth/status.ts | 4 +++- apps/cli/src/routes/completions.ts | 1 - .../lib/components/dashboard/tabs/index.ts | 5 +++- .../routes/account/api-tokens/+page.svelte | 2 +- .../src/routes/account/devices/+page.svelte | 2 +- .../src/routes/account/sessions/+page.svelte | 2 +- .../src/routes/admin/orgs/+page.svelte | 2 +- .../src/routes/admin/orgs/[slug]/+page.svelte | 2 +- .../dashboard/[slug]/members/+page.svelte | 2 +- .../dashboard/[slug]/settings/+page.svelte | 2 +- .../[slug]/settings/members/+page.svelte | 2 +- packages/db/src/client.test.ts | 10 +++++--- .../db/src/helpers/execute-bootstrap.test.ts | 24 ++++++++++--------- packages/db/src/helpers/with-transaction.ts | 2 +- packages/testing/test-helpers/src/test-db.ts | 6 +++-- 21 files changed, 47 insertions(+), 34 deletions(-) diff --git a/apps/api-server/src/__tests__/e2e/admin.test.ts b/apps/api-server/src/__tests__/e2e/admin.test.ts index 7d68b5b..eab0c23 100644 --- a/apps/api-server/src/__tests__/e2e/admin.test.ts +++ b/apps/api-server/src/__tests__/e2e/admin.test.ts @@ -29,6 +29,7 @@ import type { Kysely } from "kysely"; import type { APIContext } from "../../context.js"; import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { call } from "@orpc/server"; +import { createLoggingEmailClient } from "@reviq/emails"; import { createTestUser, describeE2E, @@ -39,7 +40,6 @@ import { uniqueTestId, withTestTransaction, } from "@reviq/test-helpers"; -import { createLoggingEmailClient } from "@reviq/emails"; import { router } from "../../router.js"; import { COOKIE_NAMES } from "../../utils/cookies.js"; import { hashToken } from "../../utils/crypto.js"; diff --git a/apps/api-server/src/__tests__/e2e/auth.test.ts b/apps/api-server/src/__tests__/e2e/auth.test.ts index cd238f6..132b6c0 100644 --- a/apps/api-server/src/__tests__/e2e/auth.test.ts +++ b/apps/api-server/src/__tests__/e2e/auth.test.ts @@ -41,6 +41,7 @@ import type { Kysely } from "kysely"; import type { APIContext } from "../../context.js"; import { beforeAll, describe, expect, test } from "bun:test"; import { call } from "@orpc/server"; +import { createLoggingEmailClient } from "@reviq/emails"; import { createTestUser, describeE2E, @@ -50,7 +51,6 @@ import { uniqueTestId, withTestTransaction, } from "@reviq/test-helpers"; -import { createLoggingEmailClient } from "@reviq/emails"; import { VirtualAuthenticator } from "@reviq/virtual-authenticator"; import { router } from "../../router.js"; import { COOKIE_NAMES } from "../../utils/cookies.js"; diff --git a/apps/api-server/src/__tests__/e2e/me.test.ts b/apps/api-server/src/__tests__/e2e/me.test.ts index 55c750d..7345fb8 100644 --- a/apps/api-server/src/__tests__/e2e/me.test.ts +++ b/apps/api-server/src/__tests__/e2e/me.test.ts @@ -23,6 +23,7 @@ import type { Kysely } from "kysely"; import type { APIContext } from "../../context.js"; import { beforeAll, describe, expect, test } from "bun:test"; import { call } from "@orpc/server"; +import { createLoggingEmailClient } from "@reviq/emails"; import { createTestUser, describeE2E, @@ -32,7 +33,6 @@ import { uniqueTestId, withTestTransaction, } from "@reviq/test-helpers"; -import { createLoggingEmailClient } from "@reviq/emails"; import { router } from "../../router.js"; import { COOKIE_NAMES } from "../../utils/cookies.js"; import { hashToken } from "../../utils/crypto.js"; diff --git a/apps/api-server/src/__tests__/e2e/orgs.test.ts b/apps/api-server/src/__tests__/e2e/orgs.test.ts index cfa91e3..7281a36 100644 --- a/apps/api-server/src/__tests__/e2e/orgs.test.ts +++ b/apps/api-server/src/__tests__/e2e/orgs.test.ts @@ -14,6 +14,7 @@ import type { Kysely } from "kysely"; import type { APIContext } from "../../context.js"; import { beforeAll, describe, expect, test } from "bun:test"; import { call } from "@orpc/server"; +import { createLoggingEmailClient } from "@reviq/emails"; import { createTestUser, describeE2E, @@ -23,7 +24,6 @@ import { uniqueTestId, withTestTransaction, } from "@reviq/test-helpers"; -import { createLoggingEmailClient } from "@reviq/emails"; import { router } from "../../router.js"; import { COOKIE_NAMES } from "../../utils/cookies.js"; import { hashToken } from "../../utils/crypto.js"; diff --git a/apps/api-server/src/__tests__/e2e/webauthn.test.ts b/apps/api-server/src/__tests__/e2e/webauthn.test.ts index 59ad8c9..9b235fe 100644 --- a/apps/api-server/src/__tests__/e2e/webauthn.test.ts +++ b/apps/api-server/src/__tests__/e2e/webauthn.test.ts @@ -12,6 +12,7 @@ import type { Kysely } from "kysely"; import type { APIContext } from "../../context.js"; import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import { call } from "@orpc/server"; +import { createLoggingEmailClient } from "@reviq/emails"; import { createTestUser, describeE2E, @@ -23,7 +24,6 @@ import { uniqueTestId, withTestTransaction, } from "@reviq/test-helpers"; -import { createLoggingEmailClient } from "@reviq/emails"; import { VirtualAuthenticator } from "@reviq/virtual-authenticator"; import { router } from "../../router.js"; import { COOKIE_NAMES } from "../../utils/cookies.js"; diff --git a/apps/api-server/src/procedures/auth/login-if-completed.ts b/apps/api-server/src/procedures/auth/login-if-completed.ts index 28ca67d..cfff24e 100644 --- a/apps/api-server/src/procedures/auth/login-if-completed.ts +++ b/apps/api-server/src/procedures/auth/login-if-completed.ts @@ -122,7 +122,8 @@ export const loginIfRequestIsCompleted = .execute(); return { session: newSession, deviceTrusted: trusted }; - }); + }, + ); // Set session cookie setCookie( diff --git a/apps/cli/src/routes/auth/status.ts b/apps/cli/src/routes/auth/status.ts index a18211d..d21f7c0 100644 --- a/apps/cli/src/routes/auth/status.ts +++ b/apps/cli/src/routes/auth/status.ts @@ -20,7 +20,9 @@ function formatRelativeTime(date: Date): string { if (diffDays === 0) { const diffHours = Math.floor(diffMs / (1000 * 60 * 60)); - return diffHours <= 0 ? "expired" : `in ${diffHours.toLocaleString()} hours`; + return diffHours <= 0 + ? "expired" + : `in ${diffHours.toLocaleString()} hours`; } if (diffDays === 1) { diff --git a/apps/cli/src/routes/completions.ts b/apps/cli/src/routes/completions.ts index 3b4d189..952ec49 100644 --- a/apps/cli/src/routes/completions.ts +++ b/apps/cli/src/routes/completions.ts @@ -44,7 +44,6 @@ function completions( _flags: Record, shell: Shell, ): void { - // biome-ignore lint/nursery/noUnnecessaryConditions: switch on union type is valid switch (shell) { case "bash": console.log("To enable bash completions for reviq, run:\n"); diff --git a/apps/publisher-dashboard/src/lib/components/dashboard/tabs/index.ts b/apps/publisher-dashboard/src/lib/components/dashboard/tabs/index.ts index 97e317e..84d583c 100644 --- a/apps/publisher-dashboard/src/lib/components/dashboard/tabs/index.ts +++ b/apps/publisher-dashboard/src/lib/components/dashboard/tabs/index.ts @@ -2,5 +2,8 @@ export { default as AdUnitTable } from "./ad-unit-table.svelte"; export { default as CountryTable } from "./country-table.svelte"; export { default as DomainTable } from "./domain-table.svelte"; export { default as KeyValueTable } from "./key-value-table.svelte"; -export { default as MetricsTable, type MetricsRow } from "./metrics-table.svelte"; +export { + default as MetricsTable, + type MetricsRow, +} from "./metrics-table.svelte"; export { default as SourceTable } from "./source-table.svelte"; diff --git a/apps/publisher-dashboard/src/routes/account/api-tokens/+page.svelte b/apps/publisher-dashboard/src/routes/account/api-tokens/+page.svelte index 1bac4b9..93dcde6 100644 --- a/apps/publisher-dashboard/src/routes/account/api-tokens/+page.svelte +++ b/apps/publisher-dashboard/src/routes/account/api-tokens/+page.svelte @@ -14,7 +14,6 @@ import { toast } from "svelte-sonner"; import { goto } from "$app/navigation"; import { resolve } from "$app/paths"; import { api } from "$lib/api/client"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Badge } from "$lib/components/ui/badge"; import { Button } from "$lib/components/ui/button"; @@ -25,6 +24,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Input } from "$lib/components/ui/input"; import { Label } from "$lib/components/ui/label"; diff --git a/apps/publisher-dashboard/src/routes/account/devices/+page.svelte b/apps/publisher-dashboard/src/routes/account/devices/+page.svelte index 3ac0550..e46a2c9 100644 --- a/apps/publisher-dashboard/src/routes/account/devices/+page.svelte +++ b/apps/publisher-dashboard/src/routes/account/devices/+page.svelte @@ -12,7 +12,6 @@ import { formatRelativeTime } from "@reviq/common"; import { createQuery, useQueryClient } from "@tanstack/svelte-query"; import { toast } from "svelte-sonner"; import { api } from "$lib/api/client"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Badge } from "$lib/components/ui/badge"; import { Button } from "$lib/components/ui/button"; @@ -23,6 +22,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; const queryClient = useQueryClient(); diff --git a/apps/publisher-dashboard/src/routes/account/sessions/+page.svelte b/apps/publisher-dashboard/src/routes/account/sessions/+page.svelte index fafa9da..1854bbe 100644 --- a/apps/publisher-dashboard/src/routes/account/sessions/+page.svelte +++ b/apps/publisher-dashboard/src/routes/account/sessions/+page.svelte @@ -15,7 +15,6 @@ import { createQuery, useQueryClient } from "@tanstack/svelte-query"; import { toast } from "svelte-sonner"; import { UAParser } from "ua-parser-js"; import { api } from "$lib/api/client"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Badge } from "$lib/components/ui/badge"; import { Button } from "$lib/components/ui/button"; @@ -26,6 +25,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; const queryClient = useQueryClient(); diff --git a/apps/publisher-dashboard/src/routes/admin/orgs/+page.svelte b/apps/publisher-dashboard/src/routes/admin/orgs/+page.svelte index d7c5ccd..e97c843 100644 --- a/apps/publisher-dashboard/src/routes/admin/orgs/+page.svelte +++ b/apps/publisher-dashboard/src/routes/admin/orgs/+page.svelte @@ -6,7 +6,6 @@ import { toast } from "svelte-sonner"; import { resolve } from "$app/paths"; import { api } from "$lib/api/client.js"; import { AdminLayout } from "$lib/components/layout"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Button } from "$lib/components/ui/button/index.js"; import { Card, @@ -14,6 +13,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card/index.js"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Skeleton } from "$lib/components/ui/skeleton/index.js"; import { Table, diff --git a/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte b/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte index 276ce93..95b0b7b 100644 --- a/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte +++ b/apps/publisher-dashboard/src/routes/admin/orgs/[slug]/+page.svelte @@ -17,7 +17,6 @@ import { page } from "$app/state"; import { api } from "$lib/api/client"; import { AdminLayout } from "$lib/components/layout"; import { OrgAvatar } from "$lib/components/org"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Button } from "$lib/components/ui/button"; import { @@ -28,6 +27,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Input } from "$lib/components/ui/input"; import { Label } from "$lib/components/ui/label"; import { diff --git a/apps/publisher-dashboard/src/routes/dashboard/[slug]/members/+page.svelte b/apps/publisher-dashboard/src/routes/dashboard/[slug]/members/+page.svelte index 944e335..5b36585 100644 --- a/apps/publisher-dashboard/src/routes/dashboard/[slug]/members/+page.svelte +++ b/apps/publisher-dashboard/src/routes/dashboard/[slug]/members/+page.svelte @@ -13,7 +13,6 @@ import { toast } from "svelte-sonner"; import { api } from "$lib/api/client"; import { DashboardLayout } from "$lib/components/layout"; import { RoleBadge } from "$lib/components/org"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Button } from "$lib/components/ui/button"; import { Card, @@ -21,6 +20,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Input } from "$lib/components/ui/input"; import { Label } from "$lib/components/ui/label"; import { diff --git a/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/+page.svelte b/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/+page.svelte index 7b6678c..7d7a6e3 100644 --- a/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/+page.svelte +++ b/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/+page.svelte @@ -14,7 +14,6 @@ import { goto } from "$app/navigation"; import { resolve } from "$app/paths"; import { api } from "$lib/api/client"; import { SettingsLayout } from "$lib/components/layout"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Alert, AlertDescription } from "$lib/components/ui/alert"; import { Button } from "$lib/components/ui/button"; import { @@ -24,6 +23,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Input } from "$lib/components/ui/input"; import { Label } from "$lib/components/ui/label"; diff --git a/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/members/+page.svelte b/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/members/+page.svelte index 888638e..1a2549c 100644 --- a/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/members/+page.svelte +++ b/apps/publisher-dashboard/src/routes/dashboard/[slug]/settings/members/+page.svelte @@ -13,7 +13,6 @@ import { toast } from "svelte-sonner"; import { api } from "$lib/api/client"; import { SettingsLayout } from "$lib/components/layout"; import { RoleBadge } from "$lib/components/org"; -import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Button } from "$lib/components/ui/button"; import { Card, @@ -21,6 +20,7 @@ import { CardHeader, CardTitle, } from "$lib/components/ui/card"; +import { ConfirmDialog } from "$lib/components/ui/confirm-dialog"; import { Input } from "$lib/components/ui/input"; import { Label } from "$lib/components/ui/label"; import { diff --git a/packages/db/src/client.test.ts b/packages/db/src/client.test.ts index ce46301..0acc798 100644 --- a/packages/db/src/client.test.ts +++ b/packages/db/src/client.test.ts @@ -15,15 +15,19 @@ const describeE2E = describe.skipIf(SKIP_DB_TESTS); describe("createDb", () => { test("throws error for empty connection string", () => { - expect(() => createDb("")).toThrow("Database connection string is required"); + expect(() => createDb("")).toThrow( + "Database connection string is required", + ); }); test("throws error for null-ish connection string", () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument -- testing edge case + // biome-ignore lint/suspicious/noExplicitAny: testing edge case with invalid input + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument expect(() => createDb(null as any)).toThrow( "Database connection string is required", ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument -- testing edge case + // biome-ignore lint/suspicious/noExplicitAny: testing edge case with invalid input + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument expect(() => createDb(undefined as any)).toThrow( "Database connection string is required", ); diff --git a/packages/db/src/helpers/execute-bootstrap.test.ts b/packages/db/src/helpers/execute-bootstrap.test.ts index f354bce..4c6062a 100644 --- a/packages/db/src/helpers/execute-bootstrap.test.ts +++ b/packages/db/src/helpers/execute-bootstrap.test.ts @@ -42,7 +42,7 @@ let testCounter = 0; const uniqueTestId = (): string => { const timestamp = Date.now(); testCounter++; - return `${timestamp}-${testCounter.toString()}`; + return `${timestamp.toString()}-${testCounter.toString()}`; }; /** Truncate all tables */ @@ -95,10 +95,8 @@ describeE2E("[e2e] executeBootstrap", () => { }); afterAll(async () => { - if (db) { - await truncateAllTables(db); - await db.destroy(); - } + await truncateAllTables(db); + await db.destroy(); }); test("creates superuser with correct email and password", async () => { @@ -263,6 +261,7 @@ describeE2E("[e2e] executeBootstrap", () => { test("throws error for password less than 8 characters", async () => { await withTestTransaction(db, async (trx) => { + // eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression await expect( executeBootstrap(trx, { email: "admin@example.com", @@ -274,6 +273,7 @@ describeE2E("[e2e] executeBootstrap", () => { test("throws error for password exactly 7 characters", async () => { await withTestTransaction(db, async (trx) => { + // eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression await expect( executeBootstrap(trx, { email: "admin@example.com", @@ -296,6 +296,7 @@ describeE2E("[e2e] executeBootstrap", () => { test("throws error for invalid email without @", async () => { await withTestTransaction(db, async (trx) => { + // eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression await expect( executeBootstrap(trx, { email: "invalidemail", @@ -326,6 +327,7 @@ describeE2E("[e2e] executeBootstrap", () => { }); // Attempt to create the same user again + // eslint-disable-next-line @typescript-eslint/await-thenable, @typescript-eslint/no-confusing-void-expression await expect( executeBootstrap(trx, { email: "admin@example.com", @@ -552,19 +554,19 @@ describeE2E("[e2e] executeBootstrap", () => { }); // Create another org and invite - const [otherOrg] = await trx + const otherOrg = await trx .insertInto("orgs") .values({ slug: `other-org-${uniqueId}`, display_name: "Other Org", }) .returning(["id"]) - .execute(); + .executeTakeFirstOrThrow(); await trx .insertInto("org_invites") .values({ - org_id: otherOrg!.id, + org_id: otherOrg.id, email: "invitee@example.com", role: "member", invited_by: result1.user.id, @@ -611,14 +613,14 @@ describeE2E("[e2e] executeBootstrap", () => { .execute(); // Add org invites (to the org, not by the user) - const [anotherUser] = await trx + const anotherUser = await trx .insertInto("users") .values({ email: `other-${uniqueId}@example.com`, display_name: "Other User", }) .returning(["id"]) - .execute(); + .executeTakeFirstOrThrow(); await trx .insertInto("org_invites") @@ -626,7 +628,7 @@ describeE2E("[e2e] executeBootstrap", () => { org_id: result1.org.id, email: "invitee@example.com", role: "member", - invited_by: anotherUser!.id, + invited_by: anotherUser.id, token: "invite-token-2", expires_at: new Date(Date.now() + 86400000), }) diff --git a/packages/db/src/helpers/with-transaction.ts b/packages/db/src/helpers/with-transaction.ts index 21137fb..724f78a 100644 --- a/packages/db/src/helpers/with-transaction.ts +++ b/packages/db/src/helpers/with-transaction.ts @@ -30,5 +30,5 @@ export async function withTransaction( } // Not in a transaction, start one - return (db as Kysely).transaction().execute(callback); + return db.transaction().execute(callback); } diff --git a/packages/testing/test-helpers/src/test-db.ts b/packages/testing/test-helpers/src/test-db.ts index 4afeff7..faf041c 100644 --- a/packages/testing/test-helpers/src/test-db.ts +++ b/packages/testing/test-helpers/src/test-db.ts @@ -202,9 +202,11 @@ export async function runMigrations(): Promise { await client.query(schemaSql); } catch (error) { // Ignore "already exists" errors - schema may have already been applied - const message = error instanceof Error ? error.message : String(error); + const message = error instanceof Error ? error.message : "Unknown error"; if (!message.includes("already exists")) { - throw new Error(`Schema application failed: ${message}`); + throw error instanceof Error + ? error + : new Error(`Schema application failed: ${message}`); } } finally { await client.end();