Pin the CJS default-import interop for adbkit, which bun and tsc disagree on. adbkit is a tsc-compiled CJS package: it sets `__esModule` and puts its real default export at `exports.default`. Upstream builds with tsc + esModuleInterop, where `import adb from '@devicefarmer/adbkit'` therefore resolves to `exports.default` - the Adb class. Bun instead applies native ESM/Node semantics, where the default of a CJS module is `module.exports` *itself*. It emits `__toESM(require(...), 1)` and, because that `isNodeMode` flag is set, unconditionally does `default = mod` regardless of `__esModule`. So `adb` ends up as the whole exports object and the Adb class is one level deeper, giving `Adb.default.createClient is not a function` at startup (AndroidAdbInterceptor is constructed eagerly by buildInterceptors, so this kills the whole server, not just Android interception). Requiring the module explicitly and reaching for `.default` ourselves makes the interop unambiguous under either toolchain. `Adb` is only ever used in type positions here, so it becomes a type-only import. diff --git a/src/interceptors/android/adb-commands.ts b/src/interceptors/android/adb-commands.ts index 26307ce..2f74c4d 100644 --- a/src/interceptors/android/adb-commands.ts +++ b/src/interceptors/android/adb-commands.ts @@ -1,7 +1,8 @@ import * as stream from 'stream'; import * as path from 'path'; -import adb, * as Adb from '@devicefarmer/adbkit'; +import type * as Adb from '@devicefarmer/adbkit'; +const adb = (require('@devicefarmer/adbkit') as typeof import('@devicefarmer/adbkit')).default; import { delay, isErrorLike } from '@httptoolkit/util'; import { logError } from '../../error-tracking';