hypermod-io / hypermod-community

Community-owned global registry and documentation hub for codemods. Write & run codemods, share them with your friends!
https://hypermod.io
MIT License
133 stars 18 forks source link

Support publishing codemods to npm from external repos #6

Closed danieldelcore closed 2 years ago

danieldelcore commented 3 years ago

For users not publishing codemods to the community folder, we want to still provide a way for consumers to bundle + publish their codemods for use with our CLI.

Related thread: https://github.com/facebook/jscodeshift/issues/126

This might look a little something like this:

@codeshift/cli publish path/to/transform

Dependency management might be an interesting challenge, but i think we can solve that by requiring transforms to also be accompanied by a codeshift.config.js file containing everything it needs.

danielo515 commented 3 years ago

I was about to propose something similar, so I'm glad someone else is also asking for it.

on your exampe I guess you mean this?

@codeshift/cli package@1.0.0 path/to/transform/*.js

It will be nice, if each package doesn't need to be a single transform but a collection of transforms. It is a bit cumbersome to ask devs to publish a separate package for each codemod they want to share. If you accept "collections" of codemods, some options to select an specific trasform may be:

  1. @codeshift/cli package@1.0.0#transform-name path/to/transform/*.js
  2. Provide a list of the available codemods on that package and make the user pick one

This will also take advantage of the codeshift .config.file

danieldelcore commented 3 years ago

Hey @danielo515, thanks for chiming in!

Just so I can have more context, what kind of codemods / collections of codemods would you consider publishing? Are they codemods intended for a specific package? For example codemods that migrate an npm package from one version to another? Or generic codemods that do things like order imports, change formatting etc?

Accept "collections" of codemods Really interesting idea! Currently, we have the concept of "motions" that are essentially parts of a single codemod. An example of a motion could be, update imports, remove props, clean up file. Authoring#motions . That might suit your use-case, otherwise maybe we can adapt that idea a bit.

It is a bit cumbersome to ask devs to publish a separate package for each codemod they want to share

For this we've created an init command that auto generates a folders for each of the codemods you want to publish. Should speed things up a bit if you're interested

danielo515 commented 3 years ago

Hello.

I am thinking more like generic or thematic collection of code mods. Right now there are two usual ways people share codemods

The first one is very tedious for the user, while the second one is wasteful and redundant, not to mention how confusing can be for end users. Some examples of this last method are:

I really wish to see this cli become an standard way to run any codemod like npx is the standard way to run cli tools from npm.

That's why I mention that having just one codemod per package, albeit simpler to implement, it's not comfortable.

I have experience with lerna and other tools, but I still prefer to not have to have 10 packages published for a bunch of codemods

danieldelcore commented 3 years ago

I still prefer to not have to have 10 packages published for a bunch of codemods

Yeah that's totally fair, thanks for sharing!

So far, codemods related to a specific npm package like @atlaskit/avatar are contained in their own package, organised by version since all of the codemods can be batched and run with the cli from the one package.

What i'd like to build next is a pretty much what you've described to a tee (I'm really glad you brought it up)!

Generic or thematic collection of code mods

My current thinking is to allow people to create preset codemods that are generic in that they don't relate to a specific published npm package like react or @atlaskit/avatar but are more utility oriented.

To give an example, you might have a set of codemods that do things like sort-imports, remove-default-import, rename-relative-imports, etc. These are generic in that they can be applied to any project.

The folder structure in my head right now is (Totally open to feedback here!):

/community
  /@preset-import-management
     /__tests__
     /sort-imports.ts
     /remove-default.ts
     /rename-relative-imports.ts
 /@preset-react
   /class-to-function-component.ts
   /remove-legacy-context.ts
   /use-shorthand-fragments.ts   

And that would be accessible via CLI in the same way you've described.

npx @codeshift/cli --preset import-management#sort-imports path/to/src

What do you think about that? Would that work for you? Just out of interest what types of codemods would you like to publish? Would love to work with you on that to get them in 😄

danielo515 commented 3 years ago

My current thinking is to allow people to create preset codemods that are generic in that they don't relate to a specific published npm package like react or @atlaskit/avatar but are more utility oriented.

While the semantics may differ, I don't see technical differences other than, maybe, being tied to an specific library version. But the version it is just one more level of grouping, so it still kind of similar.

To give an example, you might have a set of codemods that do things like sort-imports, remove-default-import, rename-relative-imports, etc. These are generic in that they can be applied to any project.

Yeah, that is exactly what I am referring to

The folder structure in my head right now is (Totally open to feedback here!):

That folder structure looks reasonable for packages/transforms that live inside this repository. But some people may not want/can go to the hurdle of contribute to an open-source project just to share a bunch of codemods they have written. Or maybe those codemods doesn't fit into a generic community project.

Those kind of codemods may benefit from this cli accepting external packages. So, similarly to the syntax you proposed can be done like this:

npx @codeshift/cli --package @danielo515/codemods#sort-imports path/to/src

If you want to take a look at the kind of stuff I'm talking about, here you have my personal codemods:

https://github.com/danielo515/codemods

Regards

danieldelcore commented 3 years ago

Ah cool, how would you expect this to work?

Because for security reasons, codemods would have to be published to the user's own NPM (ie people wouldn't be able to publish straight to this registry), which would require them to run some sort of publish command on their end, specify a package name to publish with etc. We could potentially do that, but might be fiddly for the user to set-up 🤔

so could look something like:

File structure

codemods/
  /sort-imports.ts
  codeshift.config.js

Configuration (codeshift.config.js)

{ 
  name: 'mycodemods',
 transforms: {
  sortImports: require('./sort-imports.js');
 }
}

Publish command

@codeshift/cli publish codemods/codeshift.config.js --someNPMToken 1111111

Consuming

@codeshift/cli --package mycodemods#sortImports /path/to/code

danielo515 commented 3 years ago

Hello @danieldelcore

Everything you said makes sense except the publishing part. What do you mean by "publishing straight to this registry" ? My proposition is to use public npm packages that people have, of course, published to npm

So the steps would be:

  1. Create a package following the conventions you mentioned (for ease of use, the main property of package.json should point to codeshift.config.js
  2. Publish it to npm npm publish
  3. You can use codeshift/cli to consume such package like on the last command you mentioned
  4. Codeshift will install the package locally, probably to a .codeshift configuration folder
  5. codeshift will "require" the package and run the requested transformation

Think about like the plugin system babel uses, where anyone can publish a babel package as long as they stick to the babel conventions.

Let me know if this makes sense

danieldelcore commented 3 years ago

Ahh that clears it up for me thanks!

Well in that case, I see no reason why we couldn't do that!! Your list is the plan moving forward! I'll follow up with the changes required!

danielo515 commented 3 years ago

Your list is the plan moving forward!

Do you mean the steps I outlined?

danieldelcore commented 3 years ago

Yeah haha! I was overthinking it!

danieldelcore commented 2 years ago

Closing this issue for now, this should now be available via codeshift-cli init + npm run build + npm publish