Named Export Generation Fails on NodeJS Project
tubbo opened this issue · comments
I'm converting a NodeJS project from CJS to ESM, and pretty much everything works with this CLI which is lovely in comparison to figuring out how jscodeshift
and 5to6-codemod
works! Our actual goal is to migrate everything to TypeScript, but in order to get import
statements working properly, I need to do some conversions into ESM before running ts-migrate
to mitigate errors and warnings.
Most of the codemods work, but named-export-generation
always fails for me. This occurs when I run it using this CLI, but also when I run the codemods directly with jscodeshift
and a locally installed version of 5to6-codemod. I'm running the same versions as this project specifies in package.json
.
Before:
const { GCLOUD_IMAGE_STORAGE_BUCKET_NAME } = process.env
const { DateTime } = require('luxon')
const { logger } = require('../../../../logger')
const { imageStorage } = require('./client')
const getSignedUploadUrl = async (filename, mimeType) => {
// ...
}
module.exports = {
getSignedUploadUrl,
}
After:
const { GCLOUD_IMAGE_STORAGE_BUCKET_NAME } = process.env
import { DateTime } from 'luxon';
import { logger } from '../../../../logger';
import { imageStorage } from './client.js';
const getSignedUploadUrl = async (filename, mimeType) => {
// ...
}
export default {
getSignedUploadUrl,
};
What I want here is for getSignedUploadUrl()
to become a named export (export const
), and for the default export to be deleted, because that's how my project typically imports functions like this. When you use Node with ESM, though, it doesn't recognize this older style of exporting, so I get errors all over the place unless manually go through and change named imports and exports myself, which kinda defeats the purpose of a codemod.
Not sure if this is the right place to put this, because I know the issue still exists in 5to6-codemod, but it didn't seem like that project was still getting any updates...
@tubbo 👋 So sorry that this is 3 months late... I'll never figure out GitHub notifications for new issues 😭
The reason you are getting that result is because you are overwriting the exports
, which is totally valid in commonjs, and something I used to do before trying to use TypeScript with JSDoc :P.
When you overwrite the module.exports
/exports
, you are creating something like a "commonjs export default"; if you want named exports, you need to "add" your exports to the exports
object:
module.exports.getSIgnedUploadUrl = getSIgnedUploadUrl;
// or
exports.getSIgnedUploadUrl = getSIgnedUploadUrl;
Here's an example of that in this same project.
Btw, the thing I mentioned regarding JSDoc, is that, when you want to import a type from a JS file that uses commonjs, if you overwrite the exports
, you need to do something like this:
/**
* @typedef {import('./file')['Something']} Something
*/
And sometimes it could break JSDoc; while, if you "add" to the exports
object, you could use dot notation:
/**
* @typedef {import('./file').Something} Something
*/
Again, sorry it took me so long to respond, I hope it wasn't a blocker for your migration, or that you found a workaround.