coderaiser / putout

🐊 Pluggable and configurable JavaScript Linter, code transformer and formatter, drop-in ESLint superpower replacement 💪 with built-in support for js, jsx, typescript, flow, markdown, yaml and json. Write declarative codemods in a simplest possible way 😏
https://putout.cloudcmd.io/
MIT License
705 stars 40 forks source link

Default export to name export #143

Closed killerdejavu closed 1 year ago

killerdejavu commented 1 year ago

Wanted some help on how to write a transformation which would be able to help with something like this?

From:

const x = () => {}
const y = () => {}
export default { x, y }

To:

export const x = () => {}
export const y = () => {}

We are trying to move from commonJS to module exports, and most of our commonjs exports are like this

module.exports = {
  a,
  b,
}
coderaiser commented 1 year ago

As I understand what you want is have ability to use imports this way:

import {x, y} from 'your-module';

Instead of

import yourModule from 'your-module';

Is it correct?

The simplest possible way would be:

export const report = () => `Use 'ExportNamedDeclaration' instead of 'ExportDefaultDeclaration'`;

export const fix = (path) => {
    path.node.type = 'ExportNamedDeclaration';
};

export const include = () => [
    'ExportDefaultDeclaration',
]

Converts:

const x = () => {}
const y = () => {}
export default { x, y }

To:

const x = () => {}
const y = () => {}
export { x, y }

Checkout in 🐊Putout Editor.

coderaiser commented 1 year ago

Here is more sophisticated example using scope binding:

export const report = () => `Use 'ExportNamedDeclaration' instead of 'ExportDefaultDeclaration'`;

export const fix = (path) => {
    for (const prop of path.get('declaration.properties')) {
        const {name} = prop.node.key;
        const current = path.scope.bindings[name].path.parentPath;

        replaceWith(current, ExportNamedDeclaration(current.node));
    }

    remove(path);
};

export const include = () => [
    'ExportDefaultDeclaration',
];

Converts:

export default {
    a,
}

const a = () => {};

To:

export const a = () => {};

Check out in 🐊Putout Editor.

coderaiser commented 1 year ago

Is it works for you?

so1ve commented 1 year ago

Hmmm. I don't think this transform is 100% secure because we can use default import in the first form but we need to use an "import star" in the second form.

coderaiser commented 1 year ago

So first form is works for you?