SkeLLLa/fastify-metrics

Broken ESM export in v9

Closed this issue · 3 comments

Looks like you are double-exporting a default when importing in node esm module mode.

var a = await import('fastify-metrics')
undefined
> a
[Module: null prototype] {
  __esModule: true,
  default: {
    default: <ref *1> [AsyncFunction (anonymous)] {
      default: [Circular *1],
      [Symbol(skip-override)]: true,
      [Symbol(fastify.display-name)]: 'index-auto-0',
      [Symbol(plugin-meta)]: [Object]
    }
  }
}
> 

Hi. Could you explain a bit what is the problem here?

TS code like

export default function foo() { }

Will result in

await import('foo.js')

[Module: null prototype] {
  __esModule: true,
  default: { default: [Function: foo] }
}

That's how typescript works. Or I'm missing something?

I should have mention, importing in node's ESM environment. I'm not exactly sure what is going on. Usually when importing cjs plugins you can do this:

fastify.register(import('@fastify/basic-auth'), {
  validate,
  authenticate: true
})

Instead of this

fastify.register((await import('fastify-metrics')).default, {
    defaultMetrics: { enabled: true },
    endpoint: null,
    name: 'metrics',
    routeMetrics: { enabled: true }
})

Looking at the imported objects to compare:

[Module: null prototype] {
  default: <ref *1> [AsyncFunction: basicPlugin] {
    default: [Circular *1],
    '@fastify/basicAuth': [Circular *1],
    [Symbol(skip-override)]: true,
    [Symbol(fastify.display-name)]: '@fastify/basic-auth',
    [Symbol(plugin-meta)]: { fastify: '4.x', name: '@fastify/basic-auth' }
  }
}

[Module: null prototype] {
  __esModule: true,
  default: {
    default: <ref *1> [AsyncFunction (anonymous)] {
      default: [Circular *1],
      [Symbol(skip-override)]: true,
      [Symbol(fastify.display-name)]: 'index-auto-0',
      [Symbol(plugin-meta)]: { fastify: '>=4.0.0', name: 'index-auto-0' }
    }
  }
}

I wonder if the named import provides this behavior? I would have to look into it more. I'll reopen if I get a chance to figure out. I've seen a number of ts compiled module that have the (await import('foo')).default.default problem, but it looks like its overlapping in a weird way with fastify's plugin system too.

Yes, fastify plugin also add's additional default, but this is kind-a recommended way: https://www.fastify.io/docs/latest/Reference/TypeScript/#plugins

Maybe it worth to ask this question if fastify-plugin repo? I'll try to browse other fastify plugins to see how it's done there.

There's an option to do something like

export = fastifyPlugin()

But in this case types (like plugin options) couldn't be exported from main file.