Skip to content

Fix ESM binary resolution in JavaScript client#65

Open
evanniedojadlo wants to merge 1 commit intoVibiumDev:mainfrom
evanniedojadlo:fix/esm-binary-resolution
Open

Fix ESM binary resolution in JavaScript client#65
evanniedojadlo wants to merge 1 commit intoVibiumDev:mainfrom
evanniedojadlo:fix/esm-binary-resolution

Conversation

@evanniedojadlo
Copy link
Contributor

Summary

Fixes #62 - Vibium fails to locate the clicker binary when used as an ES Module. When using Vibium in an ESM project (with "type": "module" in package.json), the library failed to find the platform-specific clicker binary, even though it was correctly installed in node_modules/@vibium/{platform}-{arch}/bin/clicker.

In Vibium fashion, I leveraged Claude Code to identify and address this issue, then personally tested and verified the fixes on macOS 26.1.

The Fix

The root cause was that binary.ts used require.resolve() to locate the platform package, which is a CommonJS function that doesn't work in ESM environments.

Solution: Implement dual CJS/ESM support using createRequire():

  1. Import createRequire from Node's built-in module package
  2. Detect runtime environment by checking for __filename (CJS) vs import.meta.url (ESM)
  3. Create a working require function using createRequire() that works in both environments
  4. Use this to resolve the platform package path

Key changes in clients/javascript/src/clicker/binary.ts:

import { fileURLToPath } from 'url';
import { createRequire } from 'module';

// Detect environment and create require function
let currentModulePath: string;
if (typeof __filename !== 'undefined') {
  currentModulePath = __filename;  // CommonJS
} else {
  currentModulePath = fileURLToPath(import.meta.url);  // ESM
}
const require = createRequire(currentModulePath);
const packagePath = require.resolve(`${packageName}/package.json`);

Test plan

Testing with Claude Code

To reproduce the issue and verify the fix:

Reproduce the issue (before fix):

Create a test ESM project with "type": "module" in package.json, install vibium, and try to launch a browser. You'll see: "Error: Could not find clicker binary"

Verify the fix (after):

Test the fix in both ESM and CommonJS modes. Create two test projects - one with "type": "module" and one without. Both should successfully launch the browser without needing CLICKER_PATH.

Claude Code prompts for testing:

# ESM test
Create a test ESM project and verify Vibium can launch a browser without CLICKER_PATH

# CommonJS test  
Create a test CommonJS project and verify backwards compatibility is maintained

🤖 Generated with Claude Code

## Problem
When using Vibium in an ESM project (with "type": "module" in package.json),
the library failed to locate the platform-specific clicker binary, even when
correctly installed. The workaround required manually setting CLICKER_PATH.

## Root Cause
The binary resolution code in `binary.ts` used `require.resolve()` which is
a CommonJS function that doesn't work properly in ESM environments. When
Node.js loads the ESM version (`dist/index.mjs`), `require` is not available.

## Solution
Implemented dual CJS/ESM support using `createRequire()` from Node's built-in
`module` package:
- Detects runtime environment by checking for `__filename` (CJS) vs `import.meta.url` (ESM)
- Uses `createRequire()` to create a working require function in both environments
- Maintains full backwards compatibility with CommonJS projects

## Testing
Verified the fix works in both modes:
- ✓ ESM mode: Browser launches without CLICKER_PATH
- ✓ CommonJS mode: Backwards compatibility maintained
- ✓ Existing test suite: 21/23 tests pass (2 pre-existing failures unrelated to this fix)

In Vibium fashion, I leveraged Claude Code to identify and address this issue,
then personally tested and verified the fixes on macOS 26.1.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.

Vibium fails to locate clicker binary when used as ES Module

1 participant