feat(cli): report legacy api bodies for manual migration

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 12:03:17 +05:30
co-authored by Claude Opus 5
parent e616ed276e
commit 4aa0973352
3 changed files with 494 additions and 0 deletions
+46
View File
@@ -35,6 +35,7 @@ import { formatWrn, parse } from "@wrnexus/syntax";
import { AI_GUIDE, CLAUDE_MD } from "./ai-guide.ts";
import { inspectProject, type DoctorCheck } from "./doctor.ts";
import { migrateApisBlock } from "./migrations/apis-block.ts";
import { detectLegacyApiBodies } from "./migrations/legacy-api-body.ts";
import { migrateModeFunctions } from "./migrations/mode-functions.ts";
import { generateApplicationTypes } from "./types.ts";
@@ -942,6 +943,51 @@ const MIGRATIONS: Migration[] = [
}
},
},
{
version: "0.9.0",
id: "report-legacy-api-bodies",
description:
"Reports legacy bare-body api entries for manual review. This is deliberately report-only: " +
"payload fields cannot be told apart from page helpers without knowing the route's response " +
"shape, so a guessed rewrite could compile while being silently wrong.",
apply(ctx) {
const appDirectory = join(ctx.appRoot, "app");
if (!existsSync(appDirectory)) return;
let foundAny = false;
for (const file of walkProjectFiles(appDirectory, ".wrn")) {
const relativeFile = relative(ctx.appRoot, file).replace(/\\/g, "/");
const source = readFileSync(file, "utf8");
let bodies: ReturnType<typeof detectLegacyApiBodies>;
try {
bodies = detectLegacyApiBodies(source);
} catch (error) {
const message = error instanceof Error ? error.message.split("\n", 1)[0] : String(error);
ctx.report.parseFailures.push(`${relativeFile}: ${message}`);
continue;
}
if (!bodies.length) continue;
foundAny = true;
for (const block of bodies) {
ctx.report.needsReview.push(
`${relativeFile}: api '${block.name}' has a legacy bare body referencing ` +
`${block.freeIdentifiers.join(", ")} — rewrite it by hand into request/response/error ` +
`sections (nothing in the source tells payload fields apart from page helpers)`,
);
}
}
if (foundAny) {
ctx.log(
"! legacy bare-body api entries need manual review: payload fields can't be told apart " +
"from page helpers without the route's response shape, so this migration reports them " +
"instead of guessing",
);
}
},
},
];
/** Release tooling uses this to require an explicit migration entry per version. */