Codemods that move an Aurelia 1 codebase toward Aurelia 2. It applies the changes that are safe to make mechanically, leaves everything else alone, and writes a report explaining what it did and what is left for you.
The tool is deliberately unambitious about the hard parts. Bootstrap, routing and anything with an ambiguous v2 equivalent is reported rather than rewritten, because a wrong automatic change in those areas costs more than doing it by hand.
npm install -g au-rogue
# or
npx au-rogue --helpcd my-aurelia-1-app
# See what would change
npx au-rogue --dry
# Read au-rogue.report.md, then apply
npx au-rogueBoth a Markdown report (au-rogue.report.md) and a JSON one (au-rogue.report.json) are written. The Markdown report groups findings into "Needs review", "Changes applied" and "Guidance", and ends with a next-steps checklist.
| Option | Default | Purpose |
|---|---|---|
--dry |
off | Report without writing files |
--sources <glob...> |
src/**/*.{ts,tsx,js,jsx} |
Source files to migrate |
--templates <glob...> |
src/**/*.{html,au}, index.html |
Templates to migrate |
--ignore <glob...> |
– | Extra paths to skip (node_modules, dist, build are always skipped) |
--only <pass...> |
– | Run only these passes |
--skip <pass...> |
– | Skip these passes |
--list-passes |
– | Print the pass names and exit |
--tsconfig <path> |
– | Load the project's tsconfig so types resolve |
--router-hooks |
off | Rename router hooks even on classes that might be dialogs |
--compat |
off | Add @aurelia/compat-v1 guidance to the report |
--report-dir <dir> |
. |
Where to write the reports |
--no-report |
– | Skip writing report files |
--fail-on-warn |
off | Exit non-zero if anything needs manual review |
--quiet |
off | Suppress everything but the summary |
Passing --tsconfig is worth it. Without resolvable types the DI pass has to infer whether a constructor parameter's type is a runtime token; with them it knows.
Running the tool twice is safe. Every pass is idempotent, and a second run over migrated code makes no further changes.
Imports. Aurelia 1 packages are remapped to their v2 equivalents, including symbol renames: HttpClient becomes IHttpClient from @aurelia/fetch-client, Router becomes IRouter from @aurelia/router, EventAggregator becomes the IEventAggregator token, bindingMode becomes BindingMode, and the thirty-odd aurelia-* packages collapse into aurelia and the scoped @aurelia/* ones. Symbols with no v2 counterpart stay where they are and get reported.
Dependency injection. @autoinject, @inject(A, B) and static inject = [A, B] all become resolve() class fields. Parameter properties convert directly; plain parameters convert when the constructor does nothing but assign them to this. v1 resolvers map across (Lazy.of(X) → lazy(X), All.of(X) → all(X), NewInstance.of(X) → newInstanceOf(X)). A constructor left empty by the conversion is removed.
Lifecycle. bind → binding, unbind → unbinding, detached → detaching. Renames only happen on classes that look like Aurelia view-models, since plenty of ordinary classes have a bind() method. Router hooks (canActivate → canLoad, activate → loading, canDeactivate → canUnload, deactivate → unloading) are renamed only for classes that are clearly routed — Aurelia 1's dialog plugin used activate/deactivate too, so --router-hooks is there for when you know better.
Templates. <require> → <import>, <router-view> → <au-viewport>, <compose> → <au-compose> (with view/view-model → template/component), <content> → <au-slot>, .delegate → .trigger, .one-way → .to-view, .call → .bind with a lambda, view-model.ref → component.ref, element.ref → ref, replace-part → au-slot, route-href → load, and <template bindable="a, b"> → <bindable> elements. Templates written inline in @customElement({ template }) get the same treatment.
Template edits are applied as offset splices against the original file, so anything the rules don't touch — interpolations, quoting style, self-closing tags, whitespace, comments — comes out byte for byte identical.
Decorators. @computedFrom(...) → @computed(...), @inlineView/@noView → @customElement({ template }), and @bindable options renamed (defaultBindingMode → mode, changeHandler → callback).
Platform. PLATFORM.moduleName('x') is unwrapped to 'x', and the import is dropped once nothing uses it.
- Bootstrap.
configure(aurelia)withaurelia.use.plugin(...)gets a worked example of the equivalentAurelia.register(...).app(Root).start(), with the v1 plugins mapped to their v2 configurations where they exist. - Routing.
configureRouter(),NavigationInstruction,router.generate()and router events are described with their v2 shape rather than rewritten. - Dependencies. The Aurelia 1 packages in
package.json, with the exactnpm install/npm uninstallcommands to swap them. - tsconfig.
experimentalDecoratorsandemitDecoratorMetadataare incompatible with Aurelia 2's TC39 decorators;importHelperswithouttslibis flagged too. - Lifecycle traps. A property that shadows a v2 hook (the classic being
loading = truenext to aloading()route hook, which silently stops the hook from running),attached()without cleanup, DOM work inbinding(). - Lost
preventDefault. Aurelia 1 called it for you on delegated events. Form submits, anchors with anhref, and submit buttons inside a form are flagged individually; every other converted handler is covered by a single per-file note rather than a warning each.
--list-passes prints them. Every finding in the report is tagged with the pass and rule that produced it, so --only and --skip let you work through a large migration one concern at a time:
npx au-rogue --only templates # just the HTML
npx au-rogue --skip lifecycle,router # everything except the risky renamesThe tool covers the mechanical middle of a migration, not the whole of it. A workable order:
- Stand up an Aurelia 2 shell (
npx makes aurelia) and rewritemain.ts. - Register
compatRegistrationfrom@aurelia/compat-v1so v1 syntax keeps working while you port. - Copy
src/over and runau-rogue --dry, thenau-rogue. - Work through the report's "Needs review" section — routing first, since the app cannot navigate without it.
- Build, run the tests, and fix what falls out.
- Remove
compatRegistrationand drop the@aurelia/compat-v1dependency. The migration is finished when nothing depends on it.
pnpm install
pnpm test
pnpm run buildThe examples/ directory holds a small Aurelia 1 app covering the patterns the tool handles; examples/run-migration.sh runs the tool against a copy of it.
MIT