Skip to content

Migration of the infamous triplet to next level, Nodenext support #4349

@climba03003

Description

@climba03003

Prerequisites

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

Issue

Currently, we aim to support different way of import and TypeScript environment which is great for developer experience.
However, the tech is growing and the current architect of the infamous triplet facing some limitation.

  1. Named export in ESM for JavaScript. expose named export fastify-cors#231
  2. TypeScript support including NodeNext and IDE typings. make type definitons "module": "nodenext" compatible fastify-cookie#184

Solution

Here is the summary on a proper approach that should be done inside the organization packages.

  1. Refactor to use explicit module.exports.

The reason behind is that node itself are using static analysis on CommonJS. Which leads to the problem, dynamic generation of named export by fastify-plugin will only be recognize by TypeScript but not Node.

// index.js
const fp = require('fastify-plugin')

function plugin() {}

// const plugin = require('plugin')
// import plugin from 'plugin' - ESM
module.exports = fp(plugin)
// import plugin from 'plugin' - TypeScript
module.exports.default = plugin
// const { plugin } = require('plugin')
// import { plugin } from 'plugin'
module.exports.plugin= plugin
  1. Refactor the typings and use namespace

The current typings is relay on the TypeScript to do module resolution and which will break the NodeNext moduleResolution.

// index.d.ts

import { FastifyPluginCallback } from 'fastify'

type Plugin = FastifyPluginCallback<plugin.PluginOptions>

declare namespace plugin {
  // plugin options
  export interface PluginOptions {}

  // other types export

  // named export
  // import { plugin } from 'plugin'
  // const { plugin } = require('plugin')
  export const plugin: Plugin
  // default export
  // import plugin from 'plugin'
  export { plugin as default }
}

declare function plugin(...params: Parameters<Plugin>): ReturnType<Plugin>

// CJS export
// const plugin = require('plugin')
export = plugin

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueGood for newcomerssemver-minorIssue or PR that should land as semver minor

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions