hypermod-community icon indicating copy to clipboard operation
hypermod-community copied to clipboard

🛝 Config specification

Open danieldelcore opened this issue 4 years ago • 4 comments

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 mod
  • description: Description of the package
  • target: Packages to target. This will be used by the github bot to trigger codemod runs in the future
  • transforms: Key-value pair of transforms organised by semver version. These are indented for package targeting
  • presets: 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:

  • transforms these are intended to move a package on NPM across versions. (v1->v2)
  • presets intended 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

danieldelcore avatar Jul 04 '21 05:07 danieldelcore

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"), 
    }
  },

danieldelcore avatar Jul 04 '21 05:07 danieldelcore

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`
      } 
    },
},

danieldelcore avatar Oct 02 '21 02:10 danieldelcore

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

danieldelcore avatar Apr 19 '22 07:04 danieldelcore

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.

danieldelcore avatar Jun 20 '22 05:06 danieldelcore