@onrails/codemod
v0.2.1
Published
Codemods for migrating onto @onrails/result (neverthrow → compat shim, and beyond)
Maintainers
Readme
@onrails/codemod
Bun-based codemods for migrating onto @onrails/result.
Install
bun add -d @onrails/codemodOr run without installing:
bunx @onrails/codemod /path/to/target-repo --dryWhat it does
By default, rewrites every from "neverthrow" import and every neverthrow
package.json dep to point at @onrails/result/compat/neverthrow.
- Walks
.ts/.tsx/.mts/.cts. Skipsnode_modules,dist,.git,.next,.turbo,coverage,build. - Rewrites only the specifier in
import/from/import(...); string mentions of"neverthrow"in regular code are left alone. - Updates
dependencies/devDependencies/peerDependenciesin every nestedpackage.jsonthat listsneverthrow, replacing it with@onrails/resultat a path relative to thatpackage.json. - Idempotent. Safe to re-run.
With --to-native, rewrites safe @onrails/result/compat/neverthrow
imports to native @onrails/result imports, then rewrites supported sync
method chains to native pipe(...) calls. This mode also reports TODO lines
for compat-only properties and unsupported import shapes that still need manual
migration.
Usage
# dry run
bunx @onrails/codemod /path/to/target-repo --dry
# apply
bunx @onrails/codemod /path/to/target-repo
# point at a local @onrails/result checkout (file: install)
bunx @onrails/codemod /path/to/target-repo \
--onrails=/Users/me/dev/onrails/packages/result
# stage 2: compat shim -> native imports
bunx @onrails/codemod /path/to/target-repo --to-native --dry
bunx @onrails/codemod /path/to/target-repo --to-nativeAfter applying:
cd target-repo
rm -rf node_modules/.bun/@onrails* node_modules/@onrails # force-refresh file: deps if using a local checkout
bun install
bun typecheck
bun testNative migration
--to-native is intentionally conservative. It rewrites imports that have a
native equivalent:
import { ok, err, Result } from "@onrails/result/compat/neverthrow";becomes:
import { ok, err } from "@onrails/result";
import type { Result } from "@onrails/result";It does not rewrite arbitrary method chains or namespace/re-export shapes yet. The CLI rewrites supported sync chains such as:
ok(1).map(double).andThen(validate).orElse(recoverInput);to:
pipe(ok(1), map(double), flatMap(validate), recover(recoverInput));Terminal .match(...) and .unwrapOr(...) become data-first native calls.
ResultAsync-looking chains stay method-style because the native async API
already supports those methods. The CLI still reports TODO lines for compat-only
surface such as .isOk(), .value, Result.fromThrowable(...),
import * as neverthrow from ..., and export { ok } from ....
Roadmap
- Generalized rename codemod (any
from "A"→from "B"+ deps): planned. - AST-backed compat method-chain rewrite to
pipe(...)/fluent(...): planned.
License
MIT
