fix: resolve all lint errors across source and test files
Some checks failed
CI / ci (push) Failing after 11s
CI / e2e (push) Has been skipped

- Fix unused function parameters (prefix with _)
- Fix unused imports in test files
- Fix import ordering in test files
- Auto-fix formatting issues across 22 files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 19:39:47 +02:00
parent e19d40e232
commit 3638e7b240
18 changed files with 47 additions and 58 deletions

View File

@@ -34,7 +34,7 @@ export function CandidateCard({
priceCents, priceCents,
categoryName, categoryName,
categoryIcon, categoryIcon,
imageFilename, imageFilename: _imageFilename,
imageUrl, imageUrl,
productUrl, productUrl,
threadId, threadId,

View File

@@ -10,7 +10,11 @@ interface ImageUploadProps {
const MAX_SIZE_BYTES = 5 * 1024 * 1024; // 5MB const MAX_SIZE_BYTES = 5 * 1024 * 1024; // 5MB
const ACCEPTED_TYPES = ["image/jpeg", "image/png", "image/webp"]; const ACCEPTED_TYPES = ["image/jpeg", "image/png", "image/webp"];
export function ImageUpload({ value, imageUrl, onChange }: ImageUploadProps) { export function ImageUpload({
value: _value,
imageUrl,
onChange,
}: ImageUploadProps) {
const [uploading, setUploading] = useState(false); const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [localPreview, setLocalPreview] = useState<string | null>(null); const [localPreview, setLocalPreview] = useState<string | null>(null);

View File

@@ -16,6 +16,7 @@ interface ItemCardProps {
imageFilename: string | null; imageFilename: string | null;
imageUrl?: string | null; imageUrl?: string | null;
productUrl?: string | null; productUrl?: string | null;
brand?: string | null;
onRemove?: () => void; onRemove?: () => void;
classification?: string; classification?: string;
onClassificationCycle?: () => void; onClassificationCycle?: () => void;
@@ -29,9 +30,10 @@ export function ItemCard({
quantity, quantity,
categoryName, categoryName,
categoryIcon, categoryIcon,
imageFilename, imageFilename: _imageFilename,
imageUrl, imageUrl,
productUrl, productUrl,
brand,
onRemove, onRemove,
classification, classification,
onClassificationCycle, onClassificationCycle,
@@ -177,9 +179,14 @@ export function ItemCard({
)} )}
</div> </div>
<div className="p-4"> <div className="p-4">
{brand && (
<p className="text-xs font-medium text-gray-400 uppercase tracking-wide mb-0.5">
{brand}
</p>
)}
<div className="flex items-center gap-1.5 mb-2"> <div className="flex items-center gap-1.5 mb-2">
<h3 className="text-sm font-semibold text-gray-900 truncate min-w-0"> <h3 className="text-sm font-semibold text-gray-900 truncate min-w-0">
{name} {brand ? name.replace(`${brand} `, "") : name}
</h3> </h3>
{quantity != null && quantity > 1 && ( {quantity != null && quantity > 1 && (
<span className="shrink-0 inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> <span className="shrink-0 inline-flex items-center px-1.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600">

View File

@@ -6,12 +6,11 @@ import { and, eq } from "drizzle-orm";
import { import {
DEV_CATEGORIES, DEV_CATEGORIES,
DEV_GLOBAL_ITEMS, DEV_GLOBAL_ITEMS,
DEV_SETUPS,
DEV_SETTINGS, DEV_SETTINGS,
DEV_SETUPS,
DEV_TAG_ASSIGNMENTS, DEV_TAG_ASSIGNMENTS,
DEV_THREADS, DEV_THREADS,
DEV_USER_ITEMS, DEV_USER_ITEMS,
categoryDisplayName,
} from "./dev-seed-data.ts"; } from "./dev-seed-data.ts";
import { db } from "./index.ts"; import { db } from "./index.ts";
import * as schema from "./schema.ts"; import * as schema from "./schema.ts";
@@ -106,7 +105,10 @@ async function seedDevData(database: Db = db) {
description: item.description, description: item.description,
}) })
.returning(); .returning();
if (!inserted) throw new Error(`Failed to insert global item: ${item.brand} ${item.model}`); if (!inserted)
throw new Error(
`Failed to insert global item: ${item.brand} ${item.model}`,
);
globalItemIds.push(inserted.id); globalItemIds.push(inserted.id);
newGlobalCount++; newGlobalCount++;
} }
@@ -185,7 +187,8 @@ async function seedDevData(database: Db = db) {
userId, userId,
}) })
.returning(); .returning();
if (!thread) throw new Error(`Failed to insert thread: ${threadDef.name}`); if (!thread)
throw new Error(`Failed to insert thread: ${threadDef.name}`);
threadResults.push({ threadId: thread.id, threadDef }); threadResults.push({ threadId: thread.id, threadDef });
} }
console.log(` ${threadResults.length} threads created.`); console.log(` ${threadResults.length} threads created.`);

View File

@@ -114,5 +114,4 @@ app.delete("/:id", async (c) => {
return c.json({ success: true }); return c.json({ success: true });
}); });
export { app as itemRoutes }; export { app as itemRoutes };

View File

@@ -1,5 +1,5 @@
import { and, asc, eq } from "drizzle-orm"; import { and, asc, eq } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts"; import type { db as prodDb } from "../../db/index.ts";
import { categories, items } from "../../db/schema.ts"; import { categories, items } from "../../db/schema.ts";
type Db = typeof prodDb; type Db = typeof prodDb;

View File

@@ -1,4 +1,4 @@
import { and, eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import type { db as prodDb } from "../../db/index.ts"; import type { db as prodDb } from "../../db/index.ts";
import { categories, globalItems, items } from "../../db/schema.ts"; import { categories, globalItems, items } from "../../db/schema.ts";
import { getOrCreateUncategorized } from "./category.service.ts"; import { getOrCreateUncategorized } from "./category.service.ts";

View File

@@ -1,7 +1,7 @@
import { and, count, eq, ilike, or, sql } from "drizzle-orm";
import type { SQL } from "drizzle-orm"; import type { SQL } from "drizzle-orm";
import { and, count, eq, ilike, or, sql } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts"; import { db as prodDb } from "../../db/index.ts";
import { globalItemTags, globalItems, items, tags } from "../../db/schema.ts"; import { globalItems, globalItemTags, items, tags } from "../../db/schema.ts";
type Db = typeof prodDb; type Db = typeof prodDb;
@@ -22,10 +22,7 @@ export async function searchGlobalItems(
const escaped = query.replace(/%/g, "\\%").replace(/_/g, "\\_"); const escaped = query.replace(/%/g, "\\%").replace(/_/g, "\\_");
const pattern = `%${escaped}%`; const pattern = `%${escaped}%`;
conditions.push( conditions.push(
or( or(ilike(globalItems.brand, pattern), ilike(globalItems.model, pattern))!,
ilike(globalItems.brand, pattern),
ilike(globalItems.model, pattern),
)!,
); );
} }
@@ -59,10 +56,7 @@ export async function searchGlobalItems(
* Get a single global item by ID with the count of user items referencing it * Get a single global item by ID with the count of user items referencing it
* via items.globalItemId. * via items.globalItemId.
*/ */
export async function getGlobalItemWithOwnerCount( export async function getGlobalItemWithOwnerCount(db: Db = prodDb, id: number) {
db: Db = prodDb,
id: number,
) {
const [item] = await db const [item] = await db
.select() .select()
.from(globalItems) .from(globalItems)

View File

@@ -359,9 +359,7 @@ export async function resolveThread(
.select() .select()
.from(globalItems) .from(globalItems)
.where(eq(globalItems.id, candidate.globalItemId)); .where(eq(globalItems.id, candidate.globalItemId));
const fallbackName = gi const fallbackName = gi ? `${gi.brand} ${gi.model}` : candidate.name;
? `${gi.brand} ${gi.model}`
: candidate.name;
insertValues = { insertValues = {
name: fallbackName, name: fallbackName,
globalItemId: candidate.globalItemId, globalItemId: candidate.globalItemId,

View File

@@ -1,4 +1,4 @@
import { and, eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import type { db as prodDb } from "../../db/index.ts"; import type { db as prodDb } from "../../db/index.ts";
import { categories, globalItems, items } from "../../db/schema.ts"; import { categories, globalItems, items } from "../../db/schema.ts";

View File

@@ -1,8 +1,8 @@
import { beforeEach, describe, expect, it } from "bun:test"; import { beforeEach, describe, expect, it } from "bun:test";
import { Hono } from "hono"; import { Hono } from "hono";
import { import {
globalItemTags,
globalItems, globalItems,
globalItemTags,
items, items,
tags, tags,
} from "../../src/db/schema.ts"; } from "../../src/db/schema.ts";
@@ -102,9 +102,7 @@ describe("Global Item Routes", () => {
.insert(globalItemTags) .insert(globalItemTags)
.values({ globalItemId: gi1.id, tagId: tag.id }); .values({ globalItemId: gi1.id, tagId: tag.id });
const res = await app.request( const res = await app.request("/api/global-items?tags=ultralight");
"/api/global-items?tags=ultralight",
);
expect(res.status).toBe(200); expect(res.status).toBe(200);
const body = await res.json(); const body = await res.json();

View File

@@ -2,7 +2,6 @@ import { beforeEach, describe, expect, it, mock } from "bun:test";
import { createHash, randomBytes } from "node:crypto"; import { createHash, randomBytes } from "node:crypto";
import { Hono } from "hono"; import { Hono } from "hono";
import { oauthRoutes, wellKnownRoute } from "../../src/server/routes/oauth.ts"; import { oauthRoutes, wellKnownRoute } from "../../src/server/routes/oauth.ts";
import { createApiKey } from "../../src/server/services/auth.service.ts";
import { createTestDb } from "../helpers/db.ts"; import { createTestDb } from "../helpers/db.ts";
// Mock @hono/oidc-auth — must be before importing routes // Mock @hono/oidc-auth — must be before importing routes
@@ -35,14 +34,14 @@ function generatePkce() {
describe("OAuth Routes", () => { describe("OAuth Routes", () => {
let app: Hono; let app: Hono;
let db: Awaited<ReturnType<typeof createTestDb>>["db"]; let _db: Awaited<ReturnType<typeof createTestDb>>["db"];
let userId: number; let _userId: number;
beforeEach(async () => { beforeEach(async () => {
const testApp = await createTestApp(); const testApp = await createTestApp();
app = testApp.app; app = testApp.app;
db = testApp.db; _db = testApp.db;
userId = testApp.userId; _userId = testApp.userId;
mockGetAuth.mockReset(); mockGetAuth.mockReset();
// Default: user is authenticated via OIDC // Default: user is authenticated via OIDC
mockGetAuth.mockReturnValue({ mockGetAuth.mockReturnValue({

View File

@@ -3,13 +3,9 @@ import { zValidator } from "@hono/zod-validator";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { Hono } from "hono"; import { Hono } from "hono";
import * as schema from "../../src/db/schema.ts"; import * as schema from "../../src/db/schema.ts";
import { parseId } from "../../src/server/lib/params.ts";
import { profileRoutes } from "../../src/server/routes/profiles.ts"; import { profileRoutes } from "../../src/server/routes/profiles.ts";
import { setupRoutes } from "../../src/server/routes/setups.ts"; import { setupRoutes } from "../../src/server/routes/setups.ts";
import { import { updateProfile } from "../../src/server/services/profile.service.ts";
getPublicSetupWithItems,
updateProfile,
} from "../../src/server/services/profile.service.ts";
import { updateProfileSchema } from "../../src/shared/schemas.ts"; import { updateProfileSchema } from "../../src/shared/schemas.ts";
import { createTestDb } from "../helpers/db.ts"; import { createTestDb } from "../helpers/db.ts";

View File

@@ -1,7 +1,7 @@
import { beforeEach, describe, expect, it } from "bun:test"; import { beforeEach, describe, expect, it } from "bun:test";
import { import {
globalItemTags,
globalItems, globalItems,
globalItemTags,
items, items,
tags, tags,
} from "../../src/db/schema.ts"; } from "../../src/db/schema.ts";
@@ -151,7 +151,7 @@ describe("Global Item Service", () => {
brand: "Revelate Designs", brand: "Revelate Designs",
model: "Terrapin System", model: "Terrapin System",
}); });
const gi2 = await insertGlobalItem(db, { const _gi2 = await insertGlobalItem(db, {
brand: "Apidura", brand: "Apidura",
model: "Handlebar Pack", model: "Handlebar Pack",
}); });
@@ -205,9 +205,7 @@ describe("Global Item Service", () => {
await tagGlobalItem(db, gi2.id, tag.id); await tagGlobalItem(db, gi2.id, tag.id);
// Both tagged bikepacking, but only one matches "terrapin" // Both tagged bikepacking, but only one matches "terrapin"
const results = await searchGlobalItems(db, "terrapin", [ const results = await searchGlobalItems(db, "terrapin", ["bikepacking"]);
"bikepacking",
]);
expect(results).toHaveLength(1); expect(results).toHaveLength(1);
expect(results[0].model).toBe("Terrapin System"); expect(results[0].model).toBe("Terrapin System");
}); });

View File

@@ -180,10 +180,7 @@ describe("Item Service", () => {
imageUrl?: string; imageUrl?: string;
}, },
) { ) {
const [row] = await testDb const [row] = await testDb.insert(globalItems).values(data).returning();
.insert(globalItems)
.values(data)
.returning();
return row; return row;
} }

View File

@@ -12,7 +12,7 @@ import {
getSetupWithItems, getSetupWithItems,
updateSetup, updateSetup,
} from "../../src/server/services/setup.service.ts"; } from "../../src/server/services/setup.service.ts";
import { createSecondTestUser, createTestDb } from "../helpers/db.ts"; import { createTestDb } from "../helpers/db.ts";
type Db = Awaited<ReturnType<typeof createTestDb>>["db"]; type Db = Awaited<ReturnType<typeof createTestDb>>["db"];
@@ -72,11 +72,11 @@ describe("Profile Service", () => {
it("returns only public setups, not private ones", async () => { it("returns only public setups, not private ones", async () => {
// Create one public and one private setup // Create one public and one private setup
const pub = await createSetup(db, userId, { const _pub = await createSetup(db, userId, {
name: "Public Setup", name: "Public Setup",
isPublic: true, isPublic: true,
}); });
const priv = await createSetup(db, userId, { name: "Private Setup" }); const _priv = await createSetup(db, userId, { name: "Private Setup" });
const profile = await getPublicProfile(db, userId); const profile = await getPublicProfile(db, userId);
expect(profile).not.toBeNull(); expect(profile).not.toBeNull();

View File

@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; import { beforeEach, describe, expect, mock, test } from "bun:test";
// Mock the S3 client send method // Mock the S3 client send method
const mockSend = mock(() => Promise.resolve({})); const mockSend = mock(() => Promise.resolve({}));

View File

@@ -1,6 +1,5 @@
import { beforeEach, describe, expect, it } from "bun:test"; import { beforeEach, describe, expect, it } from "bun:test";
import { globalItems, items } from "../../src/db/schema.ts"; import { globalItems } from "../../src/db/schema.ts";
import { eq } from "drizzle-orm";
import { import {
createCandidate, createCandidate,
createThread, createThread,
@@ -629,10 +628,7 @@ describe("Thread Service", () => {
imageUrl?: string; imageUrl?: string;
}, },
) { ) {
const [row] = await testDb const [row] = await testDb.insert(globalItems).values(data).returning();
.insert(globalItems)
.values(data)
.returning();
return row; return row;
} }