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

[altair-fastify-plugin] Add nodenext compatible typings and exports #2667

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kingston
Copy link

@kingston kingston commented Oct 1, 2024

Fixes #2666

Checks

  • Ran yarn test-build
  • Updated relevant documentations
  • Updated matching config options in altair-static

Changes proposed in this pull request:

This introduces a new index.js set of exports that are compatible with both CJS and ESM modules using the Fastify "infamous triplet" refactor for making exports support all the various import types. (fastify/fastify#4349)

I tried to do it with pure Typescript but I could not find a way to have Typescript compile into the necessary format so I created a separate set of index.js/index.d.ts which works when tested in both ESM and CJS environments.

Summary by Sourcery

Add nodenext compatible typings and exports to the altair-fastify-plugin to support both CommonJS and ESM modules, using a separate set of index.js and index.d.ts files.

New Features:

  • Introduce nodenext compatible typings and exports for the altair-fastify-plugin, supporting both CommonJS and ESM modules.

Copy link

sourcery-ai bot commented Oct 1, 2024

Reviewer's Guide by Sourcery

This pull request introduces changes to the altair-fastify-plugin to add Node.js "nodenext" compatible typings and exports. The main goal is to make the plugin compatible with both CommonJS (CJS) and ECMAScript Modules (ESM) by implementing the Fastify "infamous triplet" pattern for module exports.

Sequence Diagram

sequenceDiagram
    participant Consumer
    participant Index.js
    participant Dist
    Consumer->>Index.js: Import module
    Index.js->>Dist: Require './dist/index.js'
    Dist-->>Index.js: Return default export
    Index.js-->>Consumer: Provide CJS and ESM compatible exports
Loading

File-Level Changes

Change Details Files
Add new index.d.ts file for TypeScript declarations
  • Define FastifyAltair type as FastifyPluginCallback with PluginOptions
  • Create a namespace fastifyAltairPlugin with type exports
  • Declare fastifyAltairPlugin function with appropriate types
  • Export the module using 'export =' syntax for better compatibility
packages/altair-fastify-plugin/index.d.ts
Add new index.js file for module exports
  • Import the default export from './dist/index.js'
  • Export the plugin using module.exports for CommonJS compatibility
  • Export the plugin as default and named export for ESM compatibility
packages/altair-fastify-plugin/index.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @kingston - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@imolorhe
Copy link
Collaborator

imolorhe commented Oct 3, 2024

This looks interesting. Happy to give this approach a try. One question though, why do we need to explicitly create the index.d.ts file instead of relying on dist/index.d.ts instead?

@kingston
Copy link
Author

kingston commented Oct 4, 2024

This looks interesting. Happy to give this approach a try. One question though, why do we need to explicitly create the index.d.ts file instead of relying on dist/index.d.ts instead?

I attempted to make src/index.ts compile to the appropriate Typescript typings but I couldn't find a clean way to accomplish it since the standard Fastify approach relies on namespace to augment the function declaration and the actual export in the Altair source code is a const from fp(...) which cannot be augmented by namespace. Therefore, it was significantly easier to write manually write the index.d.ts which just re-exports the exports from dist/index.d.ts in the correct format.

This article goes into the trickiness in more detail: https://blog.andrewbran.ch/default-exports-in-commonjs-libraries/

(but the solution offered doesn't work since we are exporting a const instead of a root-level function even though the const is a function)

@imolorhe
Copy link
Collaborator

imolorhe commented Oct 5, 2024

Thanks for sharing that article! It was an interesting read. One of the points mentioned there though was that we could use the verbatimModuleSyntax tsconfig option to "force" the use of export = in the code and side step the issue completely. It sounds to me like that's the ideal solution here, but it could break instances that reference it by .default. I feel tempted to make the change though as the typing should help clarify what has changed, although might be better to do that in a major release instead.

@kingston
Copy link
Author

kingston commented Oct 7, 2024

Thanks for sharing that article! It was an interesting read. One of the points mentioned there though was that we could use the verbatimModuleSyntax tsconfig option to "force" the use of export = in the code and side step the issue completely. It sounds to me like that's the ideal solution here, but it could break instances that reference it by .default. I feel tempted to make the change though as the typing should help clarify what has changed, although might be better to do that in a major release instead.

Ah it wasn't the transpiled Typescript code but the compiled types that were proving challenging so I'm not sure verbatimModuleSyntax would help. In the types, we're exporting a function and using namespace declaration to merge an additional interface into it. But in code, we're exporting a const from fp() which means we can't use namespace declaration to merge it so it can't compile to the same types.

To avoid this normally, I export it as a dual CJS-ESM package using a tool like tsup (https://github.com/egoist/tsup?tab=readme-ov-file) but that's a larger change so didn't propose that option but it could work as well.

@kingston
Copy link
Author

kingston commented Oct 7, 2024

Thanks for sharing that article! It was an interesting read. One of the points mentioned there though was that we could use the verbatimModuleSyntax tsconfig option to "force" the use of export = in the code and side step the issue completely. It sounds to me like that's the ideal solution here, but it could break instances that reference it by .default. I feel tempted to make the change though as the typing should help clarify what has changed, although might be better to do that in a major release instead.

Ah it wasn't the transpiled Typescript code but the compiled types that were proving challenging so I'm not sure verbatimModuleSyntax would help. In the types, we're exporting a function and using namespace declaration to merge an additional interface into it. But in code, we're exporting a const from fp() which means we can't use namespace declaration to merge it so it can't compile to the same types.

To avoid this normally, I export it as a dual CJS-ESM package using a tool like tsup (https://github.com/egoist/tsup?tab=readme-ov-file) but that's a larger change so I didn't propose it initially. However, long-term that might be a nice option since it provides the right exports for each usage scenario.

@imolorhe
Copy link
Collaborator

imolorhe commented Oct 7, 2024

Right yeah it's the types. In a current PR, I'm replacing the default export with a named export, which should completely resolve this issue right? We really don't need to use default export for this, and if it's causing type confusion between systems, we might as well just get rid of it

@imolorhe
Copy link
Collaborator

imolorhe commented Oct 7, 2024

#2669

@kingston
Copy link
Author

kingston commented Oct 7, 2024

#2669

Yup that also works! It'd be a breaking change though so I assume it'd be a major release?

@imolorhe
Copy link
Collaborator

imolorhe commented Oct 7, 2024

Yeah I'll cut a major release for that change. It also updates to using fastify v5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Altair Fastify plugin not compatible with nodenext
2 participants