-
Notifications
You must be signed in to change notification settings - Fork 162
Update Migrations
Angular CLI provides a way to hook into the ng update
process for the package by exposing a collection of migration schematics.
Besides the schematics setup, the repo migration has a base UpdateChanges
class implementation that works with simple JSON config files and offers built-in functionality for:
- Typescript
- Rename a Class
- HTML Templates (all can be either renamed or removed)
- Selectors
- Directive
- Component
- Bindings
- Bound input property
- Output event binding
- Selectors
Jump to:
The project package.json has the following entry:
"ng-update": {
"migrations": "./migrations/migration-collection.json"
}
This is a special case of a collection definition (usually provided as root "schematics"
property) used by the update+migrate schematic commands. The schema for this JSON is fairly standard with the exception of additional version property:
{
"schematics": {
"migration-01": {
"version": "6.0.0",
"description": "Updates Ignite UI for Angular from v5 to v6",
"factory": "./update-6"
}
//...
The factory is a relative path that should lead to a module index.ts
that exports a function as default that returns a Rule
transformation. This is where manipulations on the source Tree
are performed, including using UpdateChanges
.
Schematic(s) that match the updated package version (and any intermediate versions) will be run as part of ng update igniteui-angular
, so each schematic should only migrate changes made in that specific version.
Because the migrations are valid schematics they can also be executed directly (useful for testing) via ng generate
:
ng g igniteui-angular/migrations/migration-collection.json:migration-XX
Where migration-XX
is the specific migration from the collection json to be run.
Schematics — An Introduction, @angular-devkit/schematics Readme, Update Command Spec
-
Start by adding a new entry to the
migration-collection.json
schematics - set the upcoming version, description and factory path.{ "schematics": { "migration-01": { ... }, "migration-02": { ... }, //... "migration-07": { "version": "6.3.0", "description": "This is the new update for 6.3.0", "factory": "./update-6_3" } } }
-
Create a folder matching the defined factory path, in this case
update-6_3
-
In the new folder create
index.ts
. Here's a boilerplate of the default export looks like this:export default function(): Rule { return (host: Tree, context: SchematicContext) => { // apply changes to host tree }; }
-
[optional] Setup and use
UpdateChanges
. See next section for more.
The class reads a local 'changes' folder to read configurations for various transformations, thus keeping the actual API fairly minimal. To use, instantiate with the current directory and Rule
arguments and then call .applyChanges()
. So the updated migration index.ts
should look like:
export default function(): Rule {
return (host: Tree, context: SchematicContext) => {
// apply changes to host tree
const update = new UpdateChanges(__dirname, host, context);
update.applyChanges();
};
}
To create configurations:
-
[optional] Create the 'changes' folder under the migration factory path if it doesn't exists yet.
-
[optional] Create config JSON files in the 'changes' folder as needed:
File Schema Use for classes.json ../../common/schema/class.schema.json TS Classes selectors.json ../../common/schema/selector.schema.json Component/Directive selectors outputs.json ../../common/schema/binding.schema.json Event Emitters inputs.json ../../common/schema/binding.schema.json Property bindings theme-props.json ../../common/schema/theme-props.schema.json Sass theme function parameters Open and empty object in the file and assign it's
$schema
to the respective value from above. This will enable auto-completion (ctrl/cmd + space) and validation for the file. -
Add to the
changes
array. Following the API (ctrl/cmd + space) is probably the best approach, but in general all change objects describe in a similar manner - with aname
orselector
property to find the element in question and either areplaceWith
value orremove
flag to specify the change action.Component/Directive will have a
type
to specify them and input/output bindings have anowner
property with bothselector
andtype
. -
Verify there are no schema errors - make sure your editor has JSON Schema support (VS Code supports by default).
Uses Typescript's AST to find only actual ts.SyntaxKind.Identifier
to avoid replacing property names or string content.
Removing a directive will also match and remove its value if bound in the template, e.g. removing igxRemoveDirective
will remove the entire [igxRemoveDirective]='value'
string from a template.
Just like directives, bindings will also be removed with their respective value. Additionally, at the moment bindings are only matched with the punctuation syntax (not prefixes) like (igxOutput)="value()"
and [igxIntput]="value"
.
In adittion to running the autmation test, you may want to manually verify that the migration is working properly. To do this, execute the following steps:
- Run the igniteui-angular repo with
npm run build:migrations
. This will output the migration code needed in the dist folder, which is otherwise not outputted if building withnpm run build:lib
. - Run
npm link igniteui-angular
for the app that needs to be migrated. - Run
ng g igniteui-angular/migrations/migration-collection.json:migration-12
If you need to debug the code that does the migration (the index.ts
file), do the following:
- Add the following object in the
launch.json
file for theigniteui-angular
repo:
{
"type": "node",
"request": "attach",
"name": "Attach by Process ID",
"processId": "${command:PickProcess}"
},
- Run
node --inspect-brk "C:\Users\hanastasov\AppData\Roaming\npm\node_modules\@angular\cli\bin\ng" g igniteui-angular/migrations/migration-collection.json:migration-12
- Choose "Attach by process ID" inside the VIsual Studio code Debug bar, and choose the correct process in the prompt dropdown.