← Public packages
@kentcdodds/codemod-runner
Run codemods over your own saved packages: scan, dry-run with real publish checks and diffs, apply, and revert.
src/apply.ts
49 lines · 1.6 KB · TypeScriptimport { requireCodemod, runStep, type StepInput } from './step.ts'
import { type CodemodRef } from './contract.ts'
import { listRunSummaries } from './ledger.ts'
import { transformPackage } from './process-package.ts'
async function assertDryRunCompleted(codemod: CodemodRef): Promise<void> {
const exportName = codemod.exportName ?? 'codemod'
const summaries = await listRunSummaries()
const completedDryRun = summaries.some(
(run) =>
run.mode === 'dry-run' &&
run.status === 'completed' &&
run.codemod?.kodyId === codemod.kodyId &&
run.codemod?.specifier === codemod.specifier &&
run.codemod?.exportName === exportName,
)
if (!completedDryRun) {
throw new Error(
`No completed dry-run found for codemod "${codemod.kodyId}/${exportName}". Run dry-run first and review the diffs before applying.`,
)
}
}
/**
* Applies a codemod to your packages: same gates as dry-run (publish
* checks, idempotency verification, drift skips), then snapshots each
* original tree into the run ledger and republishes the transformed tree.
* Requires a completed dry-run for the same codemod first. Keep the
* returned runId — it is what `revert` needs. Paged: keep calling with the
* returned runId + cursor until nextCursor is null.
*/
export default async function apply(input: StepInput = {}) {
const codemod = requireCodemod(input)
if (!input.runId) {
await assertDryRunCompleted(codemod)
}
return await runStep({
mode: 'apply',
step: input,
defaults: { limit: 1, max: 2 },
processPackage: async (run, pkg) =>
await transformPackage({
mode: 'apply',
runId: run.id,
pkg,
codemod,
}),
})
}