+
Skip to content

Conversation

fc-anjos
Copy link
Owner

Node: Standardize dual-format packaging to match established codebase patterns

This Pull Request fixes the packaging for CJS consumers of the Node package.
Previously, the CommonJS entry failed due to a Rollup bundling configuration issue in @herb-tools/node. The package used separate .cts/.mts source files, but Rollup wasn't properly bundling local dependencies for the CJS build, leaving runtime requires that failed.
This change adopts the established pattern: a single src/index.ts source file that Rollup transforms into both ESM and CJS outputs. This matches the proven strategy used by @herb-tools/core, @herb-tools/formatter, @herb-tools/highlighter, and @herb-tools/linter.

This change adopts the established pattern: a single src/index.ts source file that Rollup transforms into both ESM and CJS outputs. This matches the strategy used by @herb-tools/core, @herb-tools/formatter, @herb-tools/highlighter, and @herb-tools/linter.

No public API changes.

Expected vs Actual

  • Expected
    • Both ESM and CJS consumers can import/require @herb-tools/node, call await Herb.load(), and use the API.
  • Actual (before)
    • ESM import works.
    • CJS import fails at runtime when using the previously split sources.

Reproduction (before)

Using the built artifacts, with the previous split .mts/.cts sources:

  1. ESM import (works)
// test-esm.mjs
import { Herb } from "@herb-tools/node"

await Herb.load()
console.log("ESM works:", Herb.version)

Run:

node test-esm.mjs
# ✓ Loads and runs successfully
  1. CJS import (fails)
// test-cjs.cjs
const { Herb } = require("@herb-tools/node")

Run:

node test-cjs.cjs
# ✗ Error: Cannot find module './node-backend' (from dist/herb-node.cjs)

Even with the path changed, there'd still be the error:

TypeError: this.backendPromise is not a function
    at HerbBackendNode.load (.../node_modules/@herb-tools/core/src/herb-backend.ts:...)

Diagnosis (before)

CJS build problem:

  • src/index-cjs.cts contained require("./node-backend.js")
  • Rollup processed this as a runtime dependency, not a bundled dependency
  • The built dist/herb-node.cjs expected ./node-backend.js to exist at runtime, but it wasn't emitted
  • Additionally, the CJS version passed new Promise(...) (Promise instance) instead of () => new Promise(...) (Promise factory)

ESM build worked because:

  • Rollup properly resolved and bundled the local node-backend.ts dependency
  • It used the correct Promise factory pattern: () => new Promise(...)

Fix

Adopt the standard, project-wide packaging pattern:

  1. Use a single source file: src/index.ts for both formats.
  2. Update Rollup to emit both ESM and CJS outputs from that single source.
  3. Remove the separate .cts/.mts sources to avoid divergence and bundling issues.
  4. Update package.json type entries to the standard ./dist/types/index.d.ts.

This mirrors the approach in other packages and eliminates the non-working CJS path.


Files Changed

  • src/index-esm.mtssrc/index.ts (renamed, now single source)
  • src/index-cjs.cts (deleted, was non-working code path)
  • rollup.config.mjs (updated to use standard pattern)
  • package.json (updated type declarations)

Fixes failures when loading the CommonJS entry of @herb-tools/node while keeping the ESM entry working correctly.

Fix CommonJS entry by standardizing dual-format packaging approach

Adopt the single-source pattern used consistently across @herb-tools/core, @herb-tools/formatter, @herb-tools/highlighter, and @herb-tools/linter. Replace separate .cts/.mts source files with a single src/index.ts that Rollup transforms into both ESM and CJS outputs.

Align @herb-tools/node with the established monorepo pattern to ensure consistency, maintainability, and reliability. Preserve the existing single-entry approach with no public API changes.
@fc-anjos fc-anjos force-pushed the fix/node-cjs-packaging branch from 1ad4f6b to 1c7f6d3 Compare August 15, 2025 13:12
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

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载