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
    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