Skip to content

feat: migrate to Bun-native APIs and add Zod validation#3

Merged
betegon merged 2 commits intomainfrom
feat/bun-apis-migration
Jan 13, 2026
Merged

feat: migrate to Bun-native APIs and add Zod validation#3
betegon merged 2 commits intomainfrom
feat/bun-apis-migration

Conversation

@betegon
Copy link
Member

@betegon betegon commented Jan 13, 2026

Summary

Migrate the CLI to use Bun-native APIs following best practices from OpenCode's implementation. This improves performance, reduces dependencies, and provides a better developer experience.

Changes

Bun API Migration

  • File I/O: Replace node:fs with Bun.file() and Bun.write() for async file operations
  • Process spawning: Replace child_process with Bun.spawn() and Bun.which()
  • File discovery: Replace manual directory traversal with Bun.Glob
  • Sleep: Use Bun.sleep() instead of setTimeout wrapper

Validation

  • Add Zod for runtime config validation with schemas
  • Types are now inferred from Zod schemas

Build System

  • Replace fossilize with native Bun.build({ compile: true })
  • Support for 5 standard targets + 3 baseline (no AVX2) targets
  • New build commands:
    • bun run build - Current platform
    • bun run build:all - All platforms
    • bun run build:baseline - Include baseline builds

Developer Experience

  • Add .cursor/rules/bun-cli.mdc with comprehensive Bun development standards
  • Links to Bun docs for each API

Breaking Changes

All config functions are now async:

// Before
const token = getAuthToken();
const isAuth = isAuthenticated();

// After  
const token = await getAuthToken();
const isAuth = await isAuthenticated();

Testing

  • CLI runs: bun run dev --help
  • Build works: bun run build creates working binary
  • Binary runs: ./dist/sentry-darwin-arm64 --help

Files Changed

Category Files
Rule file .cursor/rules/bun-cli.mdc
Build script/build.ts, package.json
Types types/config.ts, types/dsn.ts, types/index.ts
Lib config.ts, browser.ts, dsn-detector.ts, api-client.ts, oauth.ts
Commands auth/*.ts, issue/*.ts, project/list.ts

- Replace node:fs with Bun.file() and Bun.write() for file operations
- Replace child_process with Bun.spawn() and Bun.which()
- Replace manual file discovery with Bun.Glob
- Add Zod for config schema validation
- Make all config functions async
- Replace fossilize with native Bun.build() for binary compilation
- Add .cursor/rules/bun-cli.mdc with Bun development standards
- Add baseline build support for older CPUs

Build commands:
  bun run build         - Build for current platform
  bun run build:all     - Build for all platforms
  bun run build:baseline - Include baseline (no AVX2) builds
- Add SENTRY_CLIENT_ID_BUILD compile-time constant
- Build script reads SENTRY_CLIENT_ID from env and injects via define
- Runtime env var override still supported (for self-hosted Sentry)
- Show warning if client ID not set at build time
- Document pattern in bun-cli.mdc rule file

Usage: SENTRY_CLIENT_ID=xxx bun run build:all
@betegon betegon merged commit f4a68d3 into main Jan 13, 2026
@betegon betegon deleted the feat/bun-apis-migration branch January 13, 2026 17:53
BYK added a commit that referenced this pull request Mar 4, 2026
…parallelize cleanup

Review Round 3 — 15 human review comments addressed:

#1: login.ts — Replace await .catch() with proper try/await/catch blocks
#2: whoami.ts + all commands — Export FRESH_ALIASES constant from list-command.ts
    to reduce boilerplate; update 15 command files to use it
#3: response-cache.ts — Bump immutable TTL from 1hr to 24hr (events/traces
    never change once created)
#4–6: response-cache.ts — Restructure URL_TIER_PATTERNS as Record<TtlTier, RegExp[]>,
    combine duplicate regex patterns into single alternations
#7: response-cache.ts — Replace localeCompare with simple < comparison for
    ASCII URL query param sorting
#8: response-cache.ts — Remove try-catch in normalizeUrl (URLs reaching the
    cache already came from a fetch, always valid)
#9: response-cache.ts — Link immutableMinTimeToLive to FALLBACK_TTL_MS.immutable
    instead of hardcoded magic number
#10: response-cache.ts — Use Object.fromEntries(headers.entries()) instead of
    manual forEach loop
#11: response-cache.ts — Remove unnecessary await on fire-and-forget unlink in
    catch block
#12: response-cache.ts — Add expiresAt field to CacheEntry for O(1) expiry
    checks during cleanup (no CachePolicy deserialization needed)
#13–15: response-cache.ts — Parallelize cache I/O (collectEntryMetadata,
    deleteExpiredEntries, evictExcessEntries) using p-limit-style concurrency
    limiter (max 8 concurrent)
BYK added a commit that referenced this pull request Mar 4, 2026
…pans

Review comments addressed:

#1: issue/list.ts FRESH_ALIASES — verified no conflict, only log/list.ts
    has f: 'follow' and it doesn't use FRESH_ALIASES
#2: cacheHeuristic 0.1 vs CLEANUP_PROBABILITY — different semantics,
    not shared (RFC heuristic vs probabilistic cleanup trigger)
#3: Simplified parallel() — replaced custom wrapper with p-limit's
    built-in .map() method (cacheIO.map(items, fn)) at all 3 call sites
#4: evictExcessEntries/deleteExpiredEntries — run both in parallel via
    Promise.all() since they operate on disjoint file sets
#5: Added Sentry instrumentation — withCacheSpan() helper in telemetry.ts,
    cache.lookup and cache.store spans in response-cache.ts with URL attrs
BYK added a commit that referenced this pull request Mar 4, 2026
…pans

Review comments addressed:

#1: issue/list.ts FRESH_ALIASES — verified no conflict, only log/list.ts
    has f: 'follow' and it doesn't use FRESH_ALIASES
#2: cacheHeuristic 0.1 vs CLEANUP_PROBABILITY — different semantics,
    not shared (RFC heuristic vs probabilistic cleanup trigger)
#3: Simplified parallel() — replaced custom wrapper with p-limit's
    built-in .map() method (cacheIO.map(items, fn)) at all 3 call sites
#4: evictExcessEntries/deleteExpiredEntries — run both in parallel via
    Promise.all() since they operate on disjoint file sets
#5: Added Sentry instrumentation — withCacheSpan() helper in telemetry.ts,
    cache.lookup and cache.store spans in response-cache.ts with URL attrs
BYK added a commit that referenced this pull request Mar 4, 2026
…pans

Review comments addressed:

#1: issue/list.ts FRESH_ALIASES — verified no conflict, only log/list.ts
    has f: 'follow' and it doesn't use FRESH_ALIASES
#2: cacheHeuristic 0.1 vs CLEANUP_PROBABILITY — different semantics,
    not shared (RFC heuristic vs probabilistic cleanup trigger)
#3: Simplified parallel() — replaced custom wrapper with p-limit's
    built-in .map() method (cacheIO.map(items, fn)) at all 3 call sites
#4: evictExcessEntries/deleteExpiredEntries — run both in parallel via
    Promise.all() since they operate on disjoint file sets
#5: Added Sentry instrumentation — withCacheSpan() helper in telemetry.ts,
    cache.lookup and cache.store spans in response-cache.ts with URL attrs
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.

1 participant