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

Typescript import example #24

Open
2 tasks done
driuqzy opened this issue Feb 27, 2025 · 10 comments · May be fixed by #30
Open
2 tasks done

Typescript import example #24

driuqzy opened this issue Feb 27, 2025 · 10 comments · May be fixed by #30
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@driuqzy
Copy link

driuqzy commented Feb 27, 2025

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

I have been unable to import this module in Typescript. Can you provide an example?

This:

import FastifyOtelInstrumentation from '@fastify/otel'
export const fastifyOtel = new FastifyOtelInstrumentation({
  servername: 'my-app',
  registerOnInitialization: true,
})

Yields:

This expression is not constructable.
  Type 'typeof import("/Users/me/git/my-app/node_modules/@fastify/otel/index")' has no construct signatures.ts(2351)

And this:

import { FastifyOtelInstrumentation } from '@fastify/otel'
export const fastifyOtel = new FastifyOtelInstrumentation({
  servername: 'my-app',
  registerOnInitialization: true,
})

Yields:

import { FastifyOtelInstrumentation } from '@fastify/otel'
         ^

SyntaxError: The requested module '@fastify/otel' does not provide an export named 'FastifyOtelInstrumentation'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:214:5)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12)

Node.js v20.10.0
@driuqzy
Copy link
Author

driuqzy commented Feb 27, 2025

I found a workaround. The problem occurs because the package is using CommonJS exports but being imported in an ES Module TypeScript context.

Here's a working solution using createRequire:

import { createRequire } from 'module'

const require = createRequire(import.meta.url)
const FastifyOtelInstrumentation = require('@fastify/otel')

export const fastifyOtel = new FastifyOtelInstrumentation({
  servername: 'my-app',
  registerOnInitialization: true,
})

Suggested Improvements

To make the package more TypeScript and ESM friendly, it would be helpful to:

  1. Add proper ESM support with dual package hazard handling
  2. Update the type definitions to correctly reflect the export structure
  3. Add examples in the README for both CommonJS and ESM usage

For reference, I'm using:

  • Node.js v20.10.0
  • TypeScript (latest)
  • @fastify/otel v0.4.0

@metcoder95
Copy link
Member

Thanks for the report! Would you like to send a PR to address it?

@metcoder95 metcoder95 added the enhancement New feature or request label Feb 28, 2025
@WendaoLee
Copy link

This workaround works well,but the sad thing is this will lost the type annonation for the package.

The best way is to add ESM support with package.

WendaoLee added a commit to WendaoLee/otel that referenced this issue Mar 4, 2025
@PrimeDominus
Copy link

I don't seem to have this problem. Maybe it's beginner's luck and/or my tsconfig.json

otel-fastify.ts:

import FastifyOtelInstrumentation from '@fastify/otel';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import {
  ConsoleSpanExporter,
  SimpleSpanProcessor,
} from '@opentelemetry/sdk-trace-base';

const exporter = new ConsoleSpanExporter();
const processor = new SimpleSpanProcessor(exporter);

const tracerProvider = new NodeTracerProvider({
  spanProcessors: [processor],
});
tracerProvider.register();
// If serverName is not provided, it will fallback to OTEL_SERVICE_NAME
// as per https://opentelemetry.io/docs/languages/sdk-configuration/general/.
const fastifyOtelInstrumentation = new FastifyOtelInstrumentation();
fastifyOtelInstrumentation.setTracerProvider(tracerProvider);

export default fastifyOtelInstrumentation;

tsconfig.json:

{
  "compilerOptions": {
    "module": "NodeNext",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "noFallthroughCasesInSwitch": false,
    "esModuleInterop": true,
    "declarationMap": true
  }
}

@metcoder95 metcoder95 linked a pull request Mar 4, 2025 that will close this issue
4 tasks
@metcoder95
Copy link
Member

Imagine the tsconfig setup matters here then

@FabianFrank
Copy link

Yes, it depends on which module resolution strategy you use in your ts config. That said, check out https://arethetypeswrong.github.io/?p=%40fastify%2Fotel%400.5.0 to see an analysis of what is wrong with the package. These are pretty common issues with esm and module resolution node16 and they've been fixed all over the ecosystem in the last few years. You shouldn't have to apply workarounds as a consumer of this package, but for now if you use node16 module resolution you have to instantiate it like so until the types are fixed:

import FastifyOtelInstrumentation from "@fastify/otel"
new FastifyOtelInstrumentation.default(...)

@metcoder95
Copy link
Member

PR for adjusting the types are welcomed

@metcoder95 metcoder95 added the good first issue Good for newcomers label Mar 12, 2025
@jsumners
Copy link
Member

Node.js 16 is unsupported.

@FabianFrank
Copy link

The moduleResolution config value being named node16 doesn't mean it is outdated. It is used by current nodejs versions and is the most recent module resolution strategy added to NodeJS. See https://www.typescriptlang.org/docs/handbook/modules/reference.html#node16-nodenext.

bcomnes added a commit to bcomnes/otel that referenced this issue Mar 17, 2025
The typescript typings were exporting using the ESM style exports, but this is a CJS module, so the exports were not resolving correctly. This switches the type export to use `export = ` syntax instead which works for ESM consumers as well as CJS consumers.

Fixes fastify#24

Signed-off-by: Bret Comnes <[email protected]>
@bcomnes bcomnes linked a pull request Mar 17, 2025 that will close this issue
4 tasks
@bcomnes
Copy link

bcomnes commented Mar 17, 2025

It's my understanding that the type export was broken for real node ESM consumers, and the root cause of the issue being a mismatch between the module being an cjs module, but the type export using esm style exports instead of the cjs export = syntax.

I believe this would fix this issue: https://github.com/fastify/otel/pull/30/files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
7 participants