migrateFromListenerMiddleware
Walks a file that uses Redux Toolkit’s createListenerMiddleware / startListening and generates one *.trigger.ts per startListening({ actionCreator, effect }) registration. The source file is left untouched — adopters review the generated triggers, wire them into their components via useEvent, then delete the middleware registration when ready.
Provided as both a programmatic API and a CLI command (triggery-codemod migrate-from-listener-middleware).
Import
Section titled “Import”Signature
Section titled “Signature”Parameters
Section titled “Parameters”| Param | Type | Required | Description |
|---|---|---|---|
file | string | yes | Path to the file declaring the middleware. |
outDir | string | no | Directory for the generated trigger files. Defaults to the source file’s directory. |
dryRun | boolean | no | Plan the changes and return them without writing to disk. |
project | ts-morph.Project | no | Pre-existing project — reuse across batches. |
Returns
Section titled “Returns”| Field | Description |
|---|---|
file | The source file that was processed. |
migrated | One entry per startListening call the codemod handled — name, output path, generated source. |
Supported shapes
Section titled “Supported shapes”The codemod recognises the canonical RTK pattern:
Other shapes — matcher, predicate, or type — are detected but not transformed in V1. The source file isn’t rewritten, so re-runs are idempotent.
| Flag | Required | Description |
|---|---|---|
--out-dir | no | Override the default output directory. |
--dry-run | no | Print planned changes without writing. |
Examples
Section titled “Examples”Programmatic
Section titled “Programmatic”Output:
What gets generated
Section titled “What gets generated”For each startListening({ actionCreator: userLoggedIn, effect: (action, api) => {...} }), the codemod writes:
The event name is derived from the actionCreator symbol’s text. The codemod doesn’t try to resolve .type on the action creator — that would require type info — so name the events by hand if your action creator slugs don’t match the slice’s type string.
Follow-up steps
Section titled “Follow-up steps”The generated triggers are starters. After running the codemod:
- Replace
listenerApi.dispatch(x)with a Triggery action — addactions.<name>to the schema, register it viauseActionin the appropriate component. - Replace
listenerApi.getState()reads with typed conditions — register viauseCondition. - Wire the new event firing: components that used to dispatch the listened-for action now call
useEvent(trigger, 'name')instead. - Once every consumer is wired, delete the
startListeningblock.