Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error importing types when moduleResolution is set to nodenext #521

Closed
anothermh opened this issue Mar 15, 2023 · 3 comments
Closed

Error importing types when moduleResolution is set to nodenext #521

anothermh opened this issue Mar 15, 2023 · 3 comments
Assignees
Labels
bug Something isn't working P2

Comments

@anothermh
Copy link

Problem

Given a simple Cloud Function written in TypeScript:

import { type Context } from '@google-cloud/functions-framework/build/src/functions'
import { type PubsubMessage } from '@google-cloud/pubsub/build/src/publisher'

export const testFunction = async (message: PubsubMessage, context: Context): Promise<void> => {
  const messageId = context.eventId as string
  console.log(`Processing messageId ${messageId}`)
}

With a tsconfig.json having:

{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "nodenext",
    "strict": true,
    "target": "es2022",
    "types": ["node"]
  },
  "include": ["src/**/*.ts"],
  "exclude": [".yarn"],
  "baseUrl": "."
}

The following error is generated:

Cannot find module '@google-cloud/functions-framework/build/src/functions' or its corresponding type declarations.ts(2307)

This error can be resolved by changing moduleResolution to node instead of nodenext.


Demonstration

demo.mov

Steps to reproduce

  1. Clone this repo
  2. Open in VSCode
  3. Install the recommended extensions
  4. Use the integrated TypeScript SDK at .yarn/sdks/typescript when prompted
  5. Reload or restart VSCode
  6. Open src/index.ts and observe the error
  7. Open tsconfig.json and change moduleResolution to node
  8. Observe the error is gone

Related GitHub issues

Related StackOverflow questions


Questions

  1. Why does this error occur with nodenext and what can be done to resolve it without switching to node?
  2. Why does the import for PubsubMessage from @google-cloud/pubsub/build/src/publisher work without errors?
  3. What is the difference between that and Context in @google-cloud/functions-framework/build/src/functions that would cause one to have an error and not the other?
@cblodgett-sauce
Copy link

This is broken on ES6 and above, not just nodeNext.

Package.json

  "dependencies": {
    "@google-cloud/functions-framework": "^3.1.3",
    "cookie-parser": "^1.4.6",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "gts": "^3.1.1",
    "helmet": "^6.0.1",
    "http-errors": "^2.0.0",
    "morgan": "^1.10.0"
  },
  "devDependencies": {
    "@istanbuljs/nyc-config-typescript": "^1.0.2",
    "@types/cookie-parser": "^1.4.3",
    "@types/cors": "^2.8.13",
    "@types/http-errors": "^2.0.1",
    "@types/mocha": "^10.0.1",
    "@types/morgan": "^1.9.4",
    "@types/node": "^18.14.6",
    "@types/supertest": "^2.0.12",
    "gts": "^3.1.1",
    "mocha": "^10.2.0",
    "nyc": "^15.1.0",
    "pre-commit": "^1.2.2",
    "supertest": "^6.3.3",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.1.2",
    "typescript": "~4.9.5"
  }

.eslintrc.json

{
  "extends": "./node_modules/gts/",
  "rules": {
    "node/no-unpublished-import": 0
  }
}

index.test.js

import getFunction from '@google-cloud/functions-framework/testing';

Error message

Cannot find module '@google-cloud/functions-framework/testing' or its corresponding type declarations.ts(2307)

@cblodgett-sauce
Copy link

They need to fix the type mappings. This is ridiculous for a cloud provider to be so far behind like this. If I wasn't forced into GCP I'd go back to AWS.

@garethgeorge
Copy link
Contributor

garethgeorge commented Jun 8, 2023

Hi all, sorry you've been running into some trouble here. I think there are two separate issues that you both have been running into that both stem from our use of an exports declaration in functions-framework-nodejs's package.json.

We declare the exports here as:

  "exports": {
    ".": {
      "types": "./build/src/index.d.ts",
      "default": "./build/src/index.js"
    },
    "./testing": {
      "types": "./build/src/testing.d.ts",
      "default": "./build/src/testing.js"
    }
  },

From the docs on the exports feature https://nodejs.org/api/packages.html#main-entry-point-export when module resolution is respecting this property all other paths in the module should be hidden and only the exported paths are available to import.

This means that when using nodenext or any other module resolution strategy that respects the exports field you should only import functions framework as:

import ... from '@google-cloud/functions-framework'
import ... from '@google-cloud/functions-framework/testing' // for testing

When using older module resolution strategies i.e. node you may still need to import internal parts functions-framework as:

import { ... } from '@google-cloud/functions-framework/build/src/testing';

All of this is to say, the preferred fix should be to update your module resolution strategy to nodenext and use the modern imports. For the issue @anothermh is running into specifically, the types in @google-cloud/functions-framework/build/src/functions that you are trying to access should be reexported from @google-cloud/functions-framework. Try using the import:

import { type Context } from '@google-cloud/functions-framework

Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working P2
Projects
None yet
Development

No branches or pull requests

5 participants