release: WRNexusJS 0.8.0
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+90 -3
View File
@@ -1,6 +1,6 @@
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
import { extname, join, resolve } from "node:path";
import { diagnose } from "@wrnexus/syntax";
import { diagnose, formatWrn } from "@wrnexus/syntax";
import { buildRouter, findRouteConflicts } from "@wrnexus/router";
import { loadAppConfig, validateAppConfig } from "@wrnexus/styles";
import { createPluginRunner, discoverPlugins } from "@wrnexus/plugin";
@@ -12,6 +12,12 @@ export interface DoctorCheck {
level?: "error" | "warning";
}
export interface DoctorRepair {
name: string;
changed: boolean;
detail: string;
}
function parseVersion(value: string): [number, number, number] {
const match = /^(\d+)\.(\d+)\.(\d+)/.exec(value.replace(/^[^\d]*/, ""));
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : [0, 0, 0];
@@ -53,6 +59,81 @@ function frameworkRanges(pkg: Record<string, unknown>): Map<string, string[]> {
return ranges;
}
export function repairProject(appRoot: string): DoctorRepair[] {
const root = resolve(appRoot);
const repairs: DoctorRepair[] = [];
const pages = join(root, "app", "pages");
if (!existsSync(pages)) {
mkdirSync(pages, { recursive: true });
repairs.push({ name: "app/pages", changed: true, detail: "created app/pages" });
}
const configNames = ["wrnexus.config.ts", "wrnexus.config.mjs", "wrnexus.config.js"];
if (!configNames.some((name) => existsSync(join(root, name)))) {
writeFileSync(join(root, "wrnexus.config.ts"), "export default {};\n", "utf8");
repairs.push({ name: "configuration", changed: true, detail: "created wrnexus.config.ts" });
}
const pkgPath = join(root, "package.json");
if (existsSync(pkgPath)) {
try {
const source = readFileSync(pkgPath, "utf8");
const pkg = JSON.parse(source) as Record<string, unknown>;
const ranges = frameworkRanges(pkg);
const preferred = [...ranges.keys()].sort((left, right) => {
const a = parseVersion(left);
const b = parseVersion(right);
return b[0] - a[0] || b[1] - a[1] || b[2] - a[2];
})[0];
let changed = false;
if (preferred && ranges.size > 1) {
for (const field of ["dependencies", "devDependencies", "peerDependencies"]) {
const dependencies = pkg[field] as Record<string, string> | undefined;
for (const name of Object.keys(dependencies ?? {})) {
if (name.startsWith("@wrnexus/") && dependencies![name] !== preferred) {
dependencies![name] = preferred;
changed = true;
}
}
}
}
const marker = (pkg.wrnexus as Record<string, unknown> | undefined) ?? {};
if (!marker.version || !versionAtLeast(String(marker.version), "0.8.0")) {
marker.version = "0.8.0";
pkg.wrnexus = marker;
changed = true;
}
if (changed) {
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
repairs.push({
name: "package.json",
changed: true,
detail: preferred
? `aligned framework packages to ${preferred}`
: "recorded 0.8.0 marker",
});
}
} catch {
repairs.push({ name: "package.json", changed: false, detail: "skipped invalid JSON" });
}
}
let formatted = 0;
for (const file of walk(join(root, "app"), ".wrn")) {
const source = readFileSync(file, "utf8");
if (diagnose(source).some((item) => item.severity === "error")) continue;
const output = formatWrn(source, { tabSize: 2, printWidth: 100, multilineAttributes: true });
if (output !== source) {
writeFileSync(file, output, "utf8");
formatted++;
}
}
if (formatted) {
repairs.push({ name: "WRN formatting", changed: true, detail: `formatted ${formatted} files` });
}
return repairs;
}
export function inspectProject(appRoot: string): DoctorCheck[] {
const root = resolve(appRoot);
const checks: DoctorCheck[] = [];
@@ -174,8 +255,12 @@ export function inspectProject(appRoot: string): DoctorCheck[] {
return checks;
}
export async function runDoctor(appRoot: string): Promise<boolean> {
export async function runDoctor(
appRoot: string,
options: { fix?: boolean } = {},
): Promise<boolean> {
const root = resolve(appRoot);
const repairs = options.fix ? repairProject(root) : [];
const checks = inspectProject(root);
try {
const config = await loadAppConfig(root);
@@ -257,6 +342,8 @@ export async function runDoctor(appRoot: string): Promise<boolean> {
}
console.log("WRNexus doctor\n");
for (const repair of repairs) console.log(`${repair.name}: ${repair.detail}`);
if (repairs.length) console.log("");
for (const check of checks) {
const optional = check.level === "warning";
console.log(` ${check.ok ? "✓" : optional ? "⚠" : "✗"} ${check.name}: ${check.detail}`);