Skip to content

Add NAPI-RS pattern support for native module loaders#2

Merged
biw merged 10 commits intomainfrom
biw/libsql-testcase
Dec 19, 2025
Merged

Add NAPI-RS pattern support for native module loaders#2
biw merged 10 commits intomainfrom
biw/libsql-testcase

Conversation

@biw
Copy link
Owner

@biw biw commented Dec 19, 2025

Summary

Implements test-driven development support for NAPI-RS auto-generated loaders used by packages like libsql-js. Adds detection and rewriting of join(__dirname, 'xxx.node') patterns and require('@scope/package') platform-specific npm packages.

Changes

  • Pattern 6/6b: Detect and rewrite join(__dirname, 'xxx.node') path expressions in existsSync calls
  • Pattern 7: Resolve npm packages with native .node files and rewrite requires
  • Tests: 13 comprehensive test cases covering real-world NAPI-RS loader scenarios

Test Results

All 147 tests passing (134 existing + 13 new)

🤖 Generated with Claude Code

biw and others added 10 commits December 18, 2025 23:03
Implements test-driven development support for NAPI-RS auto-generated
loaders used by packages like libsql-js. Adds detection and rewriting of:
- join(__dirname, 'xxx.node') path patterns (Pattern 6/6b)
- require('@scope/package-name') for platform-specific npm packages (Pattern 7)

Includes 13 comprehensive test cases covering real-world scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The test was hardcoding platform-specific filenames that didn't match
the actual platform on Linux CI. Now uses dynamic platform/arch values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…kages

This adds support for NAPI-RS/neon-rs style native module loaders that use
template literal requires like `require(`@libsql/${target}`)`.

Changes:
- Add findPlatformSpecificNativePackage helper to scan scope directories
  for platform-matching native packages (e.g., @libsql/darwin-arm64)
- Add Pattern 8 to detect template literal requires and resolve them to
  the current platform's native module package
- Update early bailout check to include template literal native package
  patterns so the transform hook processes these files
- Add 3 new tests for the template literal pattern

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rollup's getAugmentedNamespace helper has a bug where if the default export
is not a function (like native .node module exports), it creates an empty
object and only copies keys from the namespace (which only has 'default'),
NOT from the default export itself.

This caused `databaseOpen is not a function` errors because the destructured
properties weren't available on the wrapped namespace.

The fix adds `__esModule = true` marker to the native exports, which tells
getAugmentedNamespace to return the object as-is without creating an empty
wrapper.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous fix attempted to set __esModule on nativeExports, but Rollup
still wrapped it in { default: nativeExports }, so getAugmentedNamespace
never saw the marker.

This fix exploits Rollup's special handling for function defaults:
- Export a function wrapper with native module properties attached
- getAugmentedNamespace creates a callable wrapper preserving all properties
- Code can destructure databaseOpen, etc. from the result

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When filenameFormat is "preserve" (default), native module filenames now
include the package name prefix for better identification:
- @libsql/darwin-arm64/index.node → @libsql-darwin-arm64-index-ABC123.node
- sql/native.node → sql-native-ABC123.node

Scoped package names have / converted to - for file safety.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ct return

- Remove @ prefix from package names in extractPackageName to make them path-safe
  (e.g., @libsql/darwin-arm64 → libsql-darwin-arm64)
- Update test files to handle resolveId returning { id, syntheticNamedExports }
  object instead of just a string ID

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ssue)

These tests cover the fix for the "databaseOpen is not a function" error
that occurred when Rollup's getAugmentedNamespace wrapped native modules.

The fix uses syntheticNamedExports: true in resolveId to tell Rollup to
resolve named exports from the default export's properties.

Tests added:
- Verify resolveId returns syntheticNamedExports: true for hashed .node files
- Verify ES module load hook output enables destructuring
- Verify libsql-style destructuring pattern works with syntheticNamedExports

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add registerNativeFile() helper to centralize hash generation and storage
- Add detectModuleTypeWithContext() helper for module type detection
- Update resolveId, Pattern 5-8, and processNodeFile to use registerNativeFile
- Combine Pattern 6 and 6b into unified path.join/__dirname handler
- Net reduction of ~250 lines by eliminating duplicate code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@biw biw merged commit 27b1c21 into main Dec 19, 2025
1 check passed
@biw biw deleted the biw/libsql-testcase branch December 19, 2025 19:40
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