Skip to content

rhwinter/mondaydotcomorg-packagingBug

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@mondaydotcomorg/api@14.0.0ClientError named import fails under Node native ESM

@mondaydotcomorg/api advertises ClientError (re-exported from graphql-request) as a named export of the package. Its type declarations declare it, its ESM bundle re-exports it with export{ClientError}from"graphql-request", and its CJS bundle does re-export it — but via a getter-style Object.defineProperty:

Object.defineProperty(exports, "ClientError", {
  enumerable: true,
  get: function () { return t.ClientError; }   // t = require('graphql-request')
});

Node's CJS named-export static analyzer (cjs-module-lexer) does not detect this pattern as a named export. Combined with the missing exports field in package.json (which forces Node ESM to resolve the CJS bundle), the result is: TypeScript and bundlers accept the import, CJS require() sees ClientError, but import { ClientError } from '@mondaydotcomorg/api' under Node native ESM throws a SyntaxError.

Tested with

  • @mondaydotcomorg/api@14.0.0
  • Node 24.8.0 (any current Node version exhibits the same behavior — the static-analyzer limitation is long-standing)

Reproduce

npm install
npm run repro:esm-native     # ← fails with SyntaxError
npm run repro:cjs            # ← passes; ClientError IS exported, just via a getter
npm run repro:typecheck      # ← passes; types claim ClientError is exported

Diagnostics

npm run show:package-fields           # no `exports` field; main=CJS, module=ESM
npm run show:cjs-named-exports        # CJS file's direct exports.X assignments
                                      # (note: ClientError is absent — it's exported
                                      # via Object.defineProperty + getter, not direct assignment)
npm run show:esm-clienterror-export   # ESM bundle re-exports ClientError directly
npm run show:dts-clienterror-export   # .d.ts declares ClientError as a named export

Expected output of repro:esm-native

ApiClient: function
ClientError: function

Actual output of repro:esm-native

node:internal/modules/esm/module_job:254
import { ApiClient, ClientError } from '@mondaydotcomorg/api';
                    ^^^^^^^^^^^
SyntaxError: Named export 'ClientError' not found. The requested module
'@mondaydotcomorg/api' is a CommonJS module, which may not support all
module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@mondaydotcomorg/api';
const { ApiClient, ClientError } = pkg;

The suggested workaround does work for ClientError specifically (the getter is invoked when the property is accessed), but it forces every consumer of @mondaydotcomorg/api to rewrite their imports — and only because of this one re-export.

Suggested fix (one or both)

1. Make the CJS re-export of ClientError statically detectable

The simplest fix: change the CJS bundle so ClientError is exported via a direct assignment that cjs-module-lexer recognizes:

// Replace the getter-based re-export …
Object.defineProperty(exports, "ClientError", {
  enumerable: true,
  get: function () { return t.ClientError; }
});

// …with a direct assignment:
exports.ClientError = t.ClientError;

This appears to come from the Rollup configuration that produces the CJS build — likely a preserveModules/output.exports or output.interop quirk specific to re-exports from a transitive dependency. Other named exports of @mondaydotcomorg/api (e.g. ApiClient) use the direct exports.X = … form and work fine.

2. Add an exports field with import/require conditions

This is the modern convention for dual-format packages and would route Node's native ESM loader to the ESM bundle (which already re-exports ClientError correctly):

{
  "exports": {
    ".": {
      "types": "./dist/esm/index.d.ts",
      "import": "./dist/esm/index.js",
      "require": "./dist/cjs/index.js"
    }
  }
}

The legacy module field is bundler-only and has no effect on Node.

Why this is hard to catch

  • TypeScript (any moduleResolution) reads the .d.ts, sees export { ClientError } from 'graphql-request';, and emits no diagnostic.
  • Vitest / Vite / webpack prefer the module field, so they receive the ESM bundle that re-exports ClientError directly — tests pass.
  • CJS consumers (require('@mondaydotcomorg/api').ClientError) work fine because property access triggers the getter.
  • Only Node's native ESM loader trips on this, because its CJS-named-export detection is purely static and doesn't execute the getter to discover the binding. The failure typically surfaces at server boot, after CI is already green.

About

@mondaydotcomorg/api@14.0.0: ClientError import fails under Node native ESM (CJS re-export uses a getter that cjs-module-lexer doesn't detect)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors