Bug
@dagrejs/graphlib@4.0.1 ships dist/graphlib.esm.js as the exports.import target, but the package has no "type": "module" field. This means Node.js (and tools like tsx) must determine the file format from the nearest package.json, which defaults to CommonJS for plain .js files.
The result depends on the runtime:
| Runtime |
Behavior |
Outcome |
| Plain Node.js v22 |
Auto-detects ESM syntax via --experimental-detect-module |
import * as gives all named exports ✓ |
| tsx v4.x |
Treats .js as CJS (no "type": "module") |
import * as gives only { default } ✗ |
Reproduction
From inside an ESM package (with "type": "module" in its own package.json), run via tsx:
import * as graphlib from "@dagrejs/graphlib";
const { Graph, alg } = graphlib;
console.log(Object.keys(graphlib)); // [ 'default' ] ← expected: [ 'Graph', 'alg', 'json', 'version' ]
console.log(typeof Graph); // 'undefined'
console.log(typeof alg); // 'undefined'
new Graph({ directed: true }); // TypeError: Graph is not a constructor
$ npx tsx test.ts
graphlib keys: [ 'default' ]
Graph type: undefined
TypeError: Graph is not a constructor
Vs. the same file run with plain node:
$ node test.mjs
Plain node graphlib keys: [ 'Graph', 'alg', 'json', 'version' ]
Graph type: function
Root cause
package.json declares:
{
"exports": {
".": {
"import": "./dist/graphlib.esm.js",
"require": "./dist/graphlib.cjs.js"
}
}
}
But there is no "type": "module". For any runtime that doesn't auto-detect ESM syntax (Node.js without --experimental-detect-module, tsx, bundlers in strict mode), graphlib.esm.js is treated as CommonJS. The file's export { p as Graph, ... } syntax is either a parse error or silently wrapped as default.
Fix
Either of these would resolve it:
Option A — add "type": "module" to package.json:
Option B — rename the ESM output file to .mjs so its format is unambiguous regardless of package type:
"exports": {
".": {
"import": "./dist/graphlib.esm.mjs",
"require": "./dist/graphlib.cjs.js"
}
}
Workaround
Until this is fixed, consumers can use createRequire to explicitly load the CJS file:
import { createRequire } from "node:module";
import type * as graphlibTypes from "@dagrejs/graphlib";
const { Graph, alg } = createRequire(import.meta.url)("@dagrejs/graphlib") as typeof graphlibTypes;
Environment
@dagrejs/graphlib: 4.0.1
tsx: 4.21.0
- Node.js: 22.22.1
Bug
@dagrejs/graphlib@4.0.1shipsdist/graphlib.esm.jsas theexports.importtarget, but the package has no"type": "module"field. This means Node.js (and tools like tsx) must determine the file format from the nearestpackage.json, which defaults to CommonJS for plain.jsfiles.The result depends on the runtime:
--experimental-detect-moduleimport * asgives all named exports ✓.jsas CJS (no"type": "module")import * asgives only{ default }✗Reproduction
From inside an ESM package (with
"type": "module"in its ownpackage.json), run via tsx:$ npx tsx test.ts graphlib keys: [ 'default' ] Graph type: undefined TypeError: Graph is not a constructorVs. the same file run with plain
node:Root cause
package.jsondeclares:{ "exports": { ".": { "import": "./dist/graphlib.esm.js", "require": "./dist/graphlib.cjs.js" } } }But there is no
"type": "module". For any runtime that doesn't auto-detect ESM syntax (Node.js without--experimental-detect-module, tsx, bundlers in strict mode),graphlib.esm.jsis treated as CommonJS. The file'sexport { p as Graph, ... }syntax is either a parse error or silently wrapped asdefault.Fix
Either of these would resolve it:
Option A — add
"type": "module"topackage.json:{ "type": "module" }Option B — rename the ESM output file to
.mjsso its format is unambiguous regardless of package type:Workaround
Until this is fixed, consumers can use
createRequireto explicitly load the CJS file:Environment
@dagrejs/graphlib: 4.0.1tsx: 4.21.0