Skip to content

require() of ESM-only deps (https-proxy-agent, cli-cursor) breaks on Node >=20 when require(esm) is disabled; declared Node 24 support is untested #49

Description

@julia-miller-eng

Summary

@osls/compose declares support for Node 24 (engines: "^20.19.0 || ^22.13.0 || >=24") but require()s ESM-only dependencies:

  • src/utils/aws/config.js:3const { HttpsProxyAgent } = require('https-proxy-agent'); (https-proxy-agent@^9.0.0, ESM-only)
  • src/cli/Progresses.js:9const cliCursor = require('cli-cursor').default; (cli-cursor@^5.0.0, ESM-only)

These only load because Node ≥22.12 / 24 enables require(esm) by default — an experimental feature. As a result the CLI:

  1. emits ExperimentalWarning: Support for loading ES Module in require() is an experimental feature on every run, and
  2. crashes with ERR_REQUIRE_ESM whenever require(esm) is turned off — e.g. --no-experimental-require-module, a legitimate/supported setting (and the default before Node flipped it), commonly applied via NODE_OPTIONS or an .npmrc node-options= entry.

Reproduction

# Node 24.x
node --no-experimental-require-module \
  -e "require('@osls/compose/src/cli/Progresses.js')"

or, in any project whose .npmrc/env disables the flag:

npx sls <service>:deploy

Actual:

Error [ERR_REQUIRE_ESM]: require() of ES Module .../cli-cursor/index.js
from .../@osls/compose/src/cli/Progresses.js not supported.
Instead change the require of index.js to a dynamic import() ...

Once one such dependency is worked around, the next (https-proxy-agent) throws — i.e. there are multiple affected require() sites.

Expected: the CLI runs on Node 24 regardless of the require(esm) flag state, without relying on an experimental feature.

Why CI doesn't catch it

.github/workflows/tests.yml runs unit tests only on Node 20 and 22; the Node 24 job runs only formatting/lint + pack-smoke.js. No test exercises the require()-of-ESM code path on the version being advertised as supported.

Suggested fixes

  • Load these ESM-only deps via dynamic import(), or pin CJS-compatible versions (https-proxy-agent@7, cli-cursor@3), so loading never depends on require(esm).
  • Add a Node 24 unit-test job (ideally one also run with --no-experimental-require-module) to prevent regressions.

Environment

  • @osls/compose 1.9.1 (npm) / osls 4.0.0
  • Node 24.18.0, npm 11.x, Linux (GitHub Actions ubuntu-latest); also reproduced on macOS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions