Skip to content

Add transform docs in the readme #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 85 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# ember-es6-class-codemod


A collection of codemod's for ember-es6-class-codemod.

## Usage
Expand All @@ -18,21 +17,99 @@ ember-es6-class-codemod <TRANSFORM NAME> path/of/files/ or/some**/*glob.js

## Transforms

<!--TRANSFORMS_START-->
<!--TRANSFORMS_END-->
The transforms are tiered starting with simple ember objects to the complex ones including decorators and/or mixins etc. The codemods can be run targeting only specific types. For example it is possible to run the codemods targeting only `services` or `routes` in the app code.

The codemods are grouped as following

1. Simple objects (codemod: `simple-objects`)
2. Services (codemod: `services`)
3. Class helpers (codemod: `class-helpers`)
4. Routes (codemod: `routes`)
5. Components (codemod: `components`)
6. Controllers (codemod: `controllers`)
7. Routers (codemod: `routers`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should be tiering based on type of object, but instead based on features required for a given class to be transformed. Any one of these classes could require decorators, mixins, or class fields, so it's not enough to delineate by class type.

Additionally, it'll be hard to figure out what category subclasses belong to, and this strategy could result in half transformed files where one class is transpiled, but the other isn't.

I think instead we should add support for globbing, where users can define a folder or pattern that they want to apply the transforms to. This means that we always transform a whole file, no matter how many classes are part of it, but it also allows us to transform roughly by category (e.g. to transform all Routes, you would pass --include "routes/**/*").

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jscodeshift has support for glob. As per the issue here: facebook/jscodeshift#215 it relies on the shell to expand the glob. So I don't think any thing is needed from the codemods to support that, since the files passed to transform function will already be matched against the path (or pattern) passed.

I like the idea of transforming by types, but as you mentioned it might be difficult or we might be in a state where part the file can be transformed and rest can not.

The current state of codemods is designed with command line options:

  1. Transform simple objects (no options needed)
  2. Transform object with decorators (Use --decorators=true)
  3. Transform object with mixins (Use --mixins=true)
  4. Transform object with decorators and mixins (Use --mixins=true and --decorators=true)

To support types - my initial approach would be to add additional parameter --type=Controller|Route|Service|.. Using this parameter we can add different transform, for example route-transforms would have --type=route set by default. I haven't fully explored this approach yet, but I see there might be some cases where it is difficult to identify the type of the object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added #12, it matches the path to resolve the type.


At each level, the codemods handles the transforms for all previous levels and add some new transforms specific to that level. For example, codemods for `routes` will handle transforms for `services` and `simple object` and add new support for transforming `actions`. This can be illustrated with picture below:

![Transform tiers](./docs/images/tiers.png)

### Simple ember objects

| Before | After |
| --------------------------------------------- | ----------------------------------------- |
| const SimpleObject = EmberObject.extend({}); | class SimpleObject extends EmberObject {} |
| const simpleObj = SimpleObject.create(); | const simpleObj = new SimpleObject(); |
| property: value, | property = value; |
| method() { this.\_super(...arguments); } | method() { super.method(...arguments); } |
| cp: computed('p1', 'p2', function () { ... }) | @computed('p1', 'p2')<br> cp() { ... } |
| ob: observer('p1', 'p2', function () { ... }) | @observes('p1', 'p2')<br>ob() { ... } |
| ev: on('click', function() { ... }) | @on('click')<br>ev() { ... } |

For detailed examples please see `test-fixtures` in `simple-object` transform

### Services

In addition to simple object transforms, `service-transform` will do following:

| Before | After |
| ------------------------------------- | ---------------------------------- |
| const MyService = Service.extend({}); | class MyService extends Service {} |

### Class helpers (Haven't seen any example of this)

| Before | After |
| ------ | ----- |


### Routes

In addition to above mentioned transforms `route-transform` will do following

| Before | After |
| --------------------------------- | ------------------------------- |
| const MyRoute = Route.extend({}); | class MyRoute extends Route {} |
| actions: { someAction() { ... }} | @action<br>someAction() { ... } |

### Components

In addition to above mentioned transforms `controller-transform` will do following

| Before | After |
| -------------------------------------------------------------------------- | -------------------------------------------------------- |
| const MyComponent = Component.extend({}); | class MyComponent extends Component {} |
| const C = Component.extend({ tagName: 'div' }); | @tagName('div)<br> class C extends Component {} |
| const C = Component.extend({ classNames: ['a', 'b'] }); | @classNames('a', 'b')<br> class C extends Component {} |
| classNameBindings: ['isEnabled:enabled:disabled'],<br>isEnabled: false | @className('enabled', 'disabled')<br>isEnabled = false; |
| attributeBindings: ['customHref:href']<br>customHref: 'http://emberjs.com' | @attribute('href')<br>customHref = 'http://emberjs.com'; |

### Controllers

| Before | After |
| ------------------------------------------- | --------------------------------------- |
| const MyController = Controller.extend({}); | class MyController extends Controller{} |

Controller transformation would be covered in the above mentioned transforms

### Routers

| Before | After |
| ----------------------------------- | ------------------------------- |
| const MyRouter = Router.extend({}); | class MyRouter extends Router{} |

Router transformation would be covered in the above mentioned transforms

## Contributing

### Installation

* clone the repo
* change into the repo directory
* `yarn`
- clone the repo
- change into the repo directory
- `yarn`

### Running tests

* `yarn test`
- `yarn test`

### Update Documentation

* `yarn update-docs`
- `yarn update-docs`
Binary file added docs/images/tiers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.