hypermod-community
hypermod-community copied to clipboard
🛝 Config specification
codeshift.config.ts is intended to act as the source of truth for every codemod package. Configs serve a dual purpose of holding all relevant metadata and one or more codemods.
Config properties
maintainers: Github maintainer usernames to be pinged when an issue/pr is raised against a moddescription: Description of the packagetarget: Packages to target. This will be used by the github bot to trigger codemod runs in the futuretransforms: Key-value pair of transforms organised by semver version. These are indented for package targetingpresets: Generic transforms that are related to the package
Example:
export default {
maintainers: ['danieldelcore'],
description: "Codemods for upgrading @atlaskit/avatar",
target: ["@atlaskit/avatar", "@atlaskit/avatar-group"],
transforms: {
// Transforms for migrating to v1 of atlaskit avatar
"1.0.0": require("./1.0.0/transform"),
"2.0.0": require("./2.0.0/transform"),
},
presets: {
// Generic codemods intended to support the use of @atlaskit/avatar
"remove-chilren-props": require("./remove-chilren-props/transform"),
},
};
There are two types of codemods:
transformsthese are intended to move a package on NPM across versions. (v1->v2)presetsintended to support the package (remove deprecated api)
Problems
- With the separation of versioned codemods, and presets is a bit odd. Ideally we can flatten this structure a bit more
Idea:
Merge target and transforms my module name:
Single package, multiple codemods per version:
transforms: {
'@atlaskit/avatar': {
"1.0.0": require("./1.0.0/transform"),
"2.0.0": require("./2.0.0/transform"),
}
},
Multiple package, multiple codemods per version.
Note: Assuming the transform is written to target avatar and avatar-group
Note: Assuming these packages are versioned together
transforms: {
'@atlaskit/avatar, @atlaskit/avatar-group': {
"1.0.0": require("./1.0.0/transform"),
"2.0.0": require("./2.0.0/transform"),
}
},
Multiple packages, different codemods per version.
transforms: {
'@atlaskit/avatar': {
"1.0.0": require("./1.0.0/transform"),
"2.0.0": require("./2.0.0/transform"),
},
'@atlaskit/avatar-group': {
"5.0.0": require("./5.0.0/transform"),
}
},
Codemods with optional descriptions
transforms: {
'@atlaskit/avatar': {
"1.0.0": {
transform: require("./1.0.0/transform"),
description: `Short descriptions for this transform, blah blah blah`
}
},
},
I've seen a few use-cases come up recently that i want to make note of:
Scenario 1: Multiple transforms pointing to the one file.
- 1.0.0/button-transform.ts
- 1.0.0/avatar-transform.ts
- 1.0.0/tabs-transform.ts
This can be supported by creating an aggregate transform file that calls out all of the others, however that complicates adoption because it's not just a matter of dropping a config into a repo anymore.
Once idea could be to accept an array:
transforms: {
'@atlaskit/avatar': {
"1.0.0": [
require("./1.0.0/button-transform"),
require("./1.0.0/avatar-transform"),
]
},
},
Scenario 2: Multiple AST libraries for different file types
It's possible to use JSCodeshift for things other than JS files, for example CSS. If we were to lean into this more we could allow for file type globs like so:
transforms: {
'@atlaskit/avatar': {
"1.0.0": {
'js,ts,tsx': require("./1.0.0/button-transform"),
'css,scss,less': require("./1.0.0/button-transform-css"),
]
},
},
This would allow different files to have different transforms run over them
Extending configurations
In larger monorepo based projects, codemods are likely to be co-located on a per package basis. A set of codemods + config will sit with the package source. These codemods are likely not related to the "running" of the repo and are likely services exposed to consumers of those specific packages.
To make running, testing and even internal use of these codemods (for when a codmode is written to bump the package within the same repo), it would be nice for the CLI to be able to list all available codemods to be fuzzy searched and executed from the root without having to cd into the package.
How this could work is by specifying a root-level configuration / OR / utilise yarn/pnpm/npm workspaces property. IE
root-level configuration
// codeshift.config.js
{
extends: [
"build/*",
"packages/*/*",
"services/*",
]
}
utilise yarn/pnpm/npm workspaces property
"workspaces": [
"build/*",
"packages/*/*",
"services/*",
],
Using these globs the CLI could look for codeshift.config files to list for selection.