Skip to content

ci: add CI workflow + fix tsc strict union narrowing - #4

Merged
0xLeif merged 1 commit into
mainfrom
ci/add-workflow
May 3, 2026
Merged

0xLeif merged 1 commit into
mainfrom
ci/add-workflow

Conversation

@0xLeif

@0xLeif 0xLeif commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds .github/workflows/ci.yml running:
    • bun install --frozen-lockfile
    • bunx tsc --noEmit (strict typecheck)
    • shellcheck on bin/
  • Fixes 9 pre-existing TS2339 errors in src/api.ts — await c.req.json<T>().catch(() => ({})) produces a T | {} union; strict tsc refused property access on the {} branch. Annotated body variables with the explicit T type to land on the right branch.

Test plan

  • bun install --frozen-lockfile clean locally
  • bunx tsc --noEmit clean locally
  • CI passes on this PR

🤖 Generated with Claude Code

CI workflow runs `bun install --frozen-lockfile`, `bunx tsc --noEmit`,
and shellcheck on bin/.

The api handlers used `c.req.json<T>().catch(() => ({}))` which produces
a `T | {}` union — strict tsc rejects property access on the empty
object. Annotated each `body` with the explicit `T` type so `{}` (which
is structurally assignable to a type whose props are all optional) lands
on the right branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@corvid-agent

Copy link
Copy Markdown
Collaborator

👋 CorvidAgent is looking into this.

@corvid-agent corvid-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — clean and correct.

CI workflow: Solid setup. shopt -s nullglob handles an empty bin/ gracefully, and the fail-flag pattern correctly accumulates errors rather than bailing on the first one. shellcheck ships with ubuntu-latest so no explicit install needed.

Type fixes: The explicit const body: T = ... annotation is the right fix for the T | {} union narrowing issue. All annotated properties are optional, so {} from the .catch() is structurally compatible — no runtime mismatch. The existing guard conditions (if (!body.source), if (!task), etc.) already handle the empty-object fallback path correctly.

One minor note for future: if a required property is ever added to one of these body types, the .catch(() => ({})) will silently produce a type-incompatible empty object (masked by the annotation). Consider using as T or a satisfies check if that becomes a concern — but for now with all-optional fields, this is correct.

Approving. 🪶

@0xLeif
0xLeif merged commit 947ee72 into main May 3, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants