Using Codemods
Learn how to migrate your app to CanJS 3 using can-migrate.
Overview
A codemod is a transformation script that parses the AST of source code in order to do a code-aware find-and-replace refactor across multiple files. can-migrate is a CLI utility for running codemods that can help migrate your app to CanJS 3.
For example, the following CanJS 3.0 code:
import DefineMap from "can-define/map/map";
import route from "can-route";
import "can-stache/helpers/route";
const VM = DefineMap.extend({
page: {
value: "home"
}
});
route.register(":page", { page: "home" });
route.ready();
…can be transformed to this:
import DefineMap from "can-define/map/map";
import route from "can-route";
import "can-stache-route-helpers";
const VM = DefineMap.extend({
page: {
default: "home"
}
});
route.register("{page}", { page: "home" });
route.start();
Using this CLI will get you about 85% of the way to having your codebase migrated; it’s not a complete solution for a seamless migration, but it will get you significantly closer than doing the migration by hand.
For information on using codemods to upgrade from CanJS 2.3 to CanJS 3.0, check out v3.canjs.com.
Install
Install can-migrate
from npm:
npm install -g can-migrate@2
This will make the can-migrate
command available globally.
Usage
The CLI provides the following options:
Usage
$ can-migrate [<file|glob> ...]
Updates files according to the CanJS 3.0 or CanJS 4.0 migration paths (minimal, modern, future)
More info for v3.0: http://canjs.github.io/canjs/doc/migrate-3.html#Modernizedmigrationpath
More info for v4.0: http://canjs.github.io/canjs/doc/migrate-4.html
Options
--apply -a Apply transforms (instead of a dry run)
--force Apply transforms regardless of git status
--silent -s Silence output
--config -c Path to custom config file
--transform -t Specify a transform
--can-version Specify CanJS version to upgrade to
Example
Runs all the can-migrate
transforms for upgrading to CanJS 4.0 on the files that match the **/*.js
glob:
can-migrate '**/*.js' --can-version 4 --apply
Runs the can-stache/route-helpers
transform on the files that match the **/*.js
glob:
can-migrate '**/*.js' --transform can-stache/route-helpers.js --apply
You can find a complete list of version-4 transforms on GitHub.
List of CanJS 4 Transform Scripts
can-define
To run all of the version-4/can-define transforms listed below:
can-migrate '**/*.js' -t version-4/can-define/ -a
default
Running this transform:
can-migrate '**/*.js' -t version-4/can-define/default.js -a
…will transform the following:
import DefineMap from "can-define/map/map";
const VM = DefineMap.extend({
name: {
value: "Justin"
}
});
…to this:
import DefineMap from "can-define/map/map";
const VM = DefineMap.extend({
name: {
default: "Justin"
}
});
for-each
Running this transform:
can-migrate '**/*.js' -t version-4/can-define/for-each.js -a
…will transform code like this:
import DefineMap from 'can-define/map/map';
const VM = DefineMap.extend({
first: {
default: 'Kevin'
},
last: {
default: 'McCallister'
},
uppercaseAll: function() {
this.each((value, prop) => {
this[prop] = value.toUpperCase();
});
}
});
…to this:
import DefineMap from 'can-define/map/map';
const VM = DefineMap.extend({
first: {
default: 'Kevin'
},
last: {
default: 'McCallister'
},
uppercaseAll: function() {
this.forEach((value, prop) => {
this[prop] = value.toUpperCase();
});
}
});
can-queues
To run all of the version-4/can-queues transforms listed below:
can-migrate '**/*.js' -t version-4/can-queues/ -a
batch
Running this transform:
can-migrate '**/*.js' -t version-4/can-queues/batch.js -a
…will transform the following:
import canBatch from "can-event/batch/batch";
canBatch.start();
this.first = "Matthew";
this.last = "Phillips";
canBatch.stop();
…to this:
import queues from "can-queues";
queues.batch.start();
this.first = "Matthew";
this.last = "Phillips";
queues.batch.stop();
can-route
To run all of the version-4/can-route transforms listed below:
can-migrate '**/*.js' -t version-4/can-route/ -a
template
Running this transform:
can-migrate '**/*.js' -t version-4/can-route/template.js -a
…will transform the following:
can.route(":page", { page: "home" });
…to this:
can.route("{page}", { page: "home" });
register
Running this transform:
can-migrate '**/*.js' -t version-4/can-route/register.js -a
…will transform the following:
can.route("{page}", { page: "home" });
…to this:
can.route.register("{page}", { page: "home" });
start
Running this transform:
can-migrate '**/*.js' -t version-4/can-route/start.js -a
…will transform the following:
can.route.ready();
…to this:
can.route.start();
can-stache
To run all of the version-4/can-stache transforms listed below:
can-migrate '**/*.js' -t version-4/can-stache/ -a
attr-from
Running this transform:
can-migrate '**/*.js' -t version-4/can-stache/attr-from.js -a
…will transform the following:
<input type="checkbox" checked>
<my-element
prop3="something"
on:click="setFoo()"
prop4:from="foo"
prop5:to="bar"
prop5:bind="baz"
></my-element>
<a href="{{routeUrl page='away'}}">Away</a>
…to this:
<input type="checkbox" checked>
<my-element
prop3:from='"something"'
on:click="setFoo()"
prop4:from="foo"
prop5:to="bar"
prop5:bind="baz"
></my-element>
<a href="{{routeUrl page='away'}}">Away</a>
console-log
Running this transform:
can-migrate '**/*.js' -t version-4/can-stache/console-log.js -a
…will transform the following:
{{log}}
…to this:
{{console.log(this)}}
route-helpers
Running this transform:
can-migrate '**/*.js' -t version-4/can-stache/route-helpers.js -a
…will transform the following:
const routeHelpers = require('can-stache/helpers/route');
…to this:
const routeHelpers = require('can-stache-route-helpers');
...and this...
<can-import from="can-stache/helpers/route" />
…to this:
<can-import from="can-stache-route-helpers" />
scope
Running this transform:
can-migrate '**/*.js' -t version-4/can-stache/scope.js -a
…will transform the following:
<p>
{{%index}}
{{%key}}
{{%element}}
{{%event}}
{{%viewModel}}
{{%arguments}}
</p>
…to this:
<p>
{{scope.index}}
{{scope.key}}
{{scope.element}}
{{scope.event}}
{{scope.viewModel}}
{{scope.arguments}}
</p>