From 2d5595132325d7a4a29da276794334ad406b1393 Mon Sep 17 00:00:00 2001 From: sehkone Date: Thu, 6 Aug 2026 18:50:39 +0900 Subject: [PATCH] Track the current Biome release The pin sat at 2.4.9 while the rest of the organisation tracks latest. Because Biome runs with --error-on-warnings here, moving the pin alone turns CI red: 2.5.7 reports eleven findings that 2.4.9 did not. They are worth fixing rather than pinning away. noUnsafeOptionalChaining fired four times on the excluded-id sets. The Array.isArray guard already proves the value is an array, but the branch re-evaluated the optional chain, which the linter cannot narrow through. Hoisting each access into a local settles it; the cast stays, so inference and behaviour are unchanged. useOptionalChain fired seven times on !x || x.y !== "literal". Every subject is an object from a GraphQL or database result and every comparison is against a string literal, so x?.y covers the same inputs. biome.json is migrated to match what now runs: the declared schema had drifted, and linter.rules.recommended is deprecated in favour of preset and goes away in Biome 3.x. Closes #545 --- .github/workflows/ci.yml | 2 +- biome.json | 4 ++-- scripts/backfill-review-request-requested-at.ts | 4 ++-- src/app/api/activity/[id]/project-fields/route.ts | 2 +- src/app/api/activity/[id]/status/route.ts | 2 +- src/lib/dashboard/analytics.ts | 10 ++++++---- src/lib/dashboard/attention.ts | 10 ++++++---- src/lib/db/schema.ts | 2 +- src/lib/github/collectors/issues.ts | 2 +- src/lib/github/collectors/pull-requests.ts | 2 +- 10 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8dfad5e..64c1e1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - name: Setup Biome CLI uses: biomejs/setup-biome@v2 with: - version: 2.4.9 + version: latest - name: Run Biome run: biome ci --error-on-warnings . diff --git a/biome.json b/biome.json index e199d1a..e794876 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.4.9/schema.json", + "$schema": "https://biomejs.dev/schemas/2.5.7/schema.json", "vcs": { "enabled": true, "clientKind": "git", @@ -35,7 +35,7 @@ "linter": { "enabled": true, "rules": { - "recommended": true, + "preset": "recommended", "suspicious": { "noUnknownAtRules": "off" } diff --git a/scripts/backfill-review-request-requested-at.ts b/scripts/backfill-review-request-requested-at.ts index 68d853c..b6163dd 100644 --- a/scripts/backfill-review-request-requested-at.ts +++ b/scripts/backfill-review-request-requested-at.ts @@ -260,7 +260,7 @@ async function fetchReviewRequestsWithEvents( const latestEventByReviewer = new Map(); // reviewerId -> createdAt for (const event of events) { const reviewer = event.requestedReviewer; - if (!reviewer || reviewer.__typename !== "User") { + if (reviewer?.__typename !== "User") { continue; } const existing = latestEventByReviewer.get(reviewer.id); @@ -275,7 +275,7 @@ async function fetchReviewRequestsWithEvents( for (const node of reviewRequestNodes) { const reviewer = node.requestedReviewer; - if (!reviewer || reviewer.__typename !== "User") { + if (reviewer?.__typename !== "User") { continue; } const createdAt = latestEventByReviewer.get(reviewer.id) ?? null; diff --git a/src/app/api/activity/[id]/project-fields/route.ts b/src/app/api/activity/[id]/project-fields/route.ts index 7dd8def..b33715b 100644 --- a/src/app/api/activity/[id]/project-fields/route.ts +++ b/src/app/api/activity/[id]/project-fields/route.ts @@ -165,7 +165,7 @@ function sanitizePayloadValue(key: ProjectFieldKey, raw: unknown) { async function resolveIssueItem(id: string) { const detail = await getActivityItemDetail(id); - if (!detail || detail.item.type !== "issue") { + if (detail?.item.type !== "issue") { return null; } return detail; diff --git a/src/app/api/activity/[id]/status/route.ts b/src/app/api/activity/[id]/status/route.ts index c7290a7..696ed54 100644 --- a/src/app/api/activity/[id]/status/route.ts +++ b/src/app/api/activity/[id]/status/route.ts @@ -30,7 +30,7 @@ function isIssueProjectStatus(value: unknown): value is IssueProjectStatus { async function resolveIssueItem(id: string) { await ensureSchema(); const detail = await getActivityItemDetail(id); - if (!detail || detail.item.type !== "issue") { + if (detail?.item.type !== "issue") { return null; } return detail; diff --git a/src/lib/dashboard/analytics.ts b/src/lib/dashboard/analytics.ts index 062d4e5..a282b96 100644 --- a/src/lib/dashboard/analytics.ts +++ b/src/lib/dashboard/analytics.ts @@ -96,16 +96,18 @@ export async function getDashboardAnalytics( const timeZone = userTimeSettings.timezone; const dateTimeFormat = userTimeSettings.dateTimeFormat; const weekStart: WeekStart = userTimeSettings.weekStart; + const rawExcludedUserIds = config?.excluded_user_ids; const excludedUserIds = new Set( - Array.isArray(config?.excluded_user_ids) - ? (config?.excluded_user_ids as string[]).filter( + Array.isArray(rawExcludedUserIds) + ? (rawExcludedUserIds as string[]).filter( (id) => typeof id === "string" && id.trim().length > 0, ) : [], ); + const rawExcludedRepositoryIds = config?.excluded_repository_ids; const excludedRepositoryIds = new Set( - Array.isArray(config?.excluded_repository_ids) - ? (config?.excluded_repository_ids as string[]).filter( + Array.isArray(rawExcludedRepositoryIds) + ? (rawExcludedRepositoryIds as string[]).filter( (id) => typeof id === "string" && id.trim().length > 0, ) : [], diff --git a/src/lib/dashboard/attention.ts b/src/lib/dashboard/attention.ts index ecffb52..71cebd4 100644 --- a/src/lib/dashboard/attention.ts +++ b/src/lib/dashboard/attention.ts @@ -257,16 +257,18 @@ export async function getAttentionInsights(options?: { const organizationHolidaySet = await loadCombinedHolidaySet( organizationHolidayCodes, ); + const rawExcludedUserIds = config?.excluded_user_ids; const excludedUserIds = new Set( - Array.isArray(config?.excluded_user_ids) - ? (config?.excluded_user_ids as string[]).filter( + Array.isArray(rawExcludedUserIds) + ? (rawExcludedUserIds as string[]).filter( (id) => typeof id === "string" && id.trim().length > 0, ) : [], ); + const rawExcludedRepositoryIds = config?.excluded_repository_ids; const excludedRepositoryIds = new Set( - Array.isArray(config?.excluded_repository_ids) - ? (config?.excluded_repository_ids as string[]).filter( + Array.isArray(rawExcludedRepositoryIds) + ? (rawExcludedRepositoryIds as string[]).filter( (id) => typeof id === "string" && id.trim().length > 0, ) : [], diff --git a/src/lib/db/schema.ts b/src/lib/db/schema.ts index 49e326c..2ff935a 100644 --- a/src/lib/db/schema.ts +++ b/src/lib/db/schema.ts @@ -821,7 +821,7 @@ let ensurePromise: Promise | null = null; function isPublicSchemaPermissionError(error: unknown) { const dbError = error as DatabaseError | null; - if (!dbError || dbError.code !== "42501") { + if (dbError?.code !== "42501") { return false; } diff --git a/src/lib/github/collectors/issues.ts b/src/lib/github/collectors/issues.ts index e60829d..5a84c8a 100644 --- a/src/lib/github/collectors/issues.ts +++ b/src/lib/github/collectors/issues.ts @@ -413,7 +413,7 @@ async function fetchDiscussionCommentRepliesConnection( }, ); const node = data.node; - if (!node || node.__typename !== "DiscussionComment") { + if (node?.__typename !== "DiscussionComment") { return null; } return node.replies ?? null; diff --git a/src/lib/github/collectors/pull-requests.ts b/src/lib/github/collectors/pull-requests.ts index e6cb189..4c0e88c 100644 --- a/src/lib/github/collectors/pull-requests.ts +++ b/src/lib/github/collectors/pull-requests.ts @@ -80,7 +80,7 @@ async function syncReviewRequestsSnapshot( const latestEventByReviewer = new Map(); // reviewerId -> createdAt for (const node of events) { - if (!node || node.__typename !== "ReviewRequestedEvent") { + if (node?.__typename !== "ReviewRequestedEvent") { continue; } const reviewer = node.requestedReviewer;