Skip to content

aws: prebuilt provider packages cannot be imported under strict Node ESM resolution (missing package.json exports map) #386

Description

@DJAlPee

Expected Behavior

Importing a prebuilt provider construct subpath, e.g.:

import { DataAwsCallerIdentity } from '@cdktn/provider-aws/lib/data-aws-caller-identity';

should resolve and run under Node's strict ESM resolution ("type": "module"), the same way it already works under CommonJS.

Actual Behavior

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '.../node_modules/@cdktn/provider-aws/lib/data-aws-caller-identity' is not supported resolving ES modules imported from <bundle>.js
Did you mean to import "@cdktn/provider-aws/lib/data-aws-caller-identity/index.js"?

Prebuilt provider packages expose each resource as a subpath that resolves to a directory (e.g. @cdktn/provider-aws/lib/data-aws-caller-identity/{index.js,index.d.ts}), with no "exports" map in package.json and no "type" field. CommonJS require() resolves this fine via the legacy directory→index.js fallback, but Node's strict ESM resolver does not support directory imports at all, so any consumer bundling/running as ESM and referencing these subpaths fails outright.

This is a different, unaddressed case from #100 ("provider-generator: support ESM"), which only covers the locally generated TypeScript bindings produced by cdktn get / @cdktn/provider-generator (fixed via #150/#151 by adding file extensions to relative imports). The prebuilt, published provider packages are built via a completely different pipeline (jsii + jsii-pacmak/projen) and ship compiled JS, not TypeScript source, so that fix does not apply here.

Steps to Reproduce

  1. In an ESM project ("type": "module" in package.json), import a prebuilt provider construct:
    import { DataAwsCallerIdentity } from '@cdktn/provider-aws/lib/data-aws-caller-identity';
  2. Bundle with esbuild format: 'esm', externalizing @cdktn/provider-aws (leaving the import specifier intact for Node to resolve at runtime), or just run the un-bundled import directly under Node.
  3. Execute with plain node.

Versions

language: typescript
node: v22.23.2
cdktn: 0.23.2
constructs: 10.6.0
@cdktn/provider-aws: 24.3.0
arch: arm64
os: darwin (macOS)

Migration Context

Not sure / don't remember — we migrated to CDKTN before switching our build to ESM, so we can't confirm whether this reproduced under the original cdktf. Given the root cause (a package.json shape issue shared by the jsii/projen-based prebuilt-provider generator), it seems plausible this also affects/affected upstream cdktf's prebuilt provider packages, since they're generated by essentially the same pipeline — but this is unverified.

Upstream cdktf Issue

Not confirmed/found — flagging as plausible given the shared jsii/projen-based generation pipeline (see Migration Context above), but we did not locate a specific existing upstream report for this exact symptom.

Providers

┌───────┬──────────────────┬─────────┬────────────┬─────────────────────┬─────────────────┐
│ Provider Name │ Provider Version │ CDKTN   │ Constraint │ Package Name        │ Package Version │
├───────┼──────────────────┼─────────┼────────────┼─────────────────────┼─────────────────┤
│ aws            │ 6.47.0           │ ^0.23.0 │            │ @cdktn/provider-aws     │ 24.3.0          │
│ archive        │ 2.8.0            │ ^0.23.0 │            │ @cdktn/provider-archive │ 13.1.0          │
│ external       │ 2.4.0            │ ^0.23.0 │            │ @cdktn/provider-external│ 13.1.0          │
│ null           │ 3.3.0            │ ^0.23.0 │            │ @cdktn/provider-null    │ 13.1.0          │
│ random         │ 3.9.0            │ ^0.23.0 │            │ @cdktn/provider-random  │ 14.1.0          │
└───────┴──────────────────┴─────────┴────────────┴─────────────────────┴─────────────────┘

Possible Solutions

Generate an "exports" map (mapping each lib/<resource> subpath to its concrete index.js/index.d.ts) in the prebuilt-provider package template (jsii/projen-based), so these packages can be imported under strict ESM resolution — independent of, and in addition to, the generator-level fix already done for locally-generated bindings in #100.

Workarounds

Keep the bundler output format as CommonJS (e.g. esbuild format: 'cjs') for any code that imports @cdktn/provider-* subpaths, even in an otherwise-ESM ("type": "module") project — CJS's directory→index.js resolution fallback works fine, only the strict ESM resolver rejects it.

Anything Else?

Found while converting a CDKTF app's build to a single bundled file with esbuild; bundling to format: 'esm' (our original goal) fails specifically because of this, forcing us to keep format: 'cjs' for that bundle.

References

Help Wanted

  • I'm interested in contributing a fix myself

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions