Skip to content

graphql CLI plugin generates NodeNext-incompatible metadata imports (missing .js extension) #3870

@dunak-debug

Description

@dunak-debug

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When using the Nest CLI GraphQL plugin with module/moduleResolution: "nodenext", generated src/metadata.ts contains extensionless dynamic imports like:

import("./api/auth/auth.types")

TypeScript then fails during type-check/build with TS2307 for those generated imports.

nest build (or tsc --noEmit) fails with errors from generated src/metadata.ts:

error TS2307: Cannot find module './api/user/user.types' or its corresponding type declarations.
error TS2307: Cannot find module './api/auth/auth.types' or its corresponding type declarations.
error TS2307: Cannot find module './api/customer/customer.types' or its corresponding type declarations.

Minimum reproduction code

https://gist.github.com/dunak-debug/43c43098e6bba67eeb2c41a34de30211

Steps to reproduce

  1. Create a Nest app using @nestjs/graphql plugin in nest-cli.json.
  2. Use TypeScript module + moduleResolution as nodenext.
  3. Configure GraphQLModule.forRoot({ metadata }) using generated metadata file.
  4. Run nest build or tsc --noEmit.

Expected behavior

Generated metadata should be compatible with NodeNext.
For example, generated imports should include .js:

import("./api/auth/auth.types.js")

so type-check/build succeeds without workarounds.

Package version

13.2.4

Graphql version

graphql: 16.13.0
@nestjs/mercurius: 13.2.4
mercurius: 16.7.0

NestJS version

11.1.14

Node.js version

24.14.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

TypeScript: 5.9.3
pnpm: 10.30.3
I confirmed a local patch changing metadata import emission from:

--- a/dist/plugin/visitors/model-class.visitor.js
+++ b/dist/plugin/visitors/model-class.visitor.js
@@ -27,7 +27,8 @@ class ModelClassVisitor {
         const metadataWithImports = [];
         Object.keys(this._collectedMetadata).forEach((filePath) => {
             const metadata = this._collectedMetadata[filePath];
-            const path = filePath.replace(/\.[jt]s$/, '');
+            // Emit explicit .js specifiers so generated metadata.ts is compatible with NodeNext.
+            const path = filePath.replace(/\.[jt]s$/, '.js');
             const importExpr = ts.factory.createCallExpression(ts.factory.createToken(ts.SyntaxKind.ImportKeyword), undefined, [ts.factory.createStringLiteral(path)]);
             metadataWithImports.push([importExpr, metadata]);
         });

resolves the issue in NodeNext projects.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions