|
|
#!/usr/bin/env tsx
|
|
|
/** 快速分析 baseline.har 中 axel/quote 响应结构(阶段0 诊断) */
|
|
|
import fs from "node:fs";
|
|
|
import { BASELINE_HAR } from "./lib/paths";
|
|
|
|
|
|
type HarEntry = {
|
|
|
request: { url: string; method: string };
|
|
|
response: { status: number; content?: { text?: string } };
|
|
|
};
|
|
|
|
|
|
const har = JSON.parse(fs.readFileSync(BASELINE_HAR, "utf8")) as {
|
|
|
log?: { entries?: HarEntry[] };
|
|
|
};
|
|
|
|
|
|
const axel = (har.log?.entries ?? []).filter(
|
|
|
(e) =>
|
|
|
e.request.url.includes("axel/quote") &&
|
|
|
e.response.status >= 200 &&
|
|
|
e.response.status < 300,
|
|
|
);
|
|
|
|
|
|
console.log(`axel/quote 2xx 响应数: ${axel.length}`);
|
|
|
|
|
|
for (const [i, entry] of axel.entries()) {
|
|
|
const text = entry.response.content?.text;
|
|
|
if (!text?.trim()) {
|
|
|
console.log(`[${i}] 无 body`);
|
|
|
continue;
|
|
|
}
|
|
|
let body: Record<string, unknown>;
|
|
|
try {
|
|
|
body = JSON.parse(text) as Record<string, unknown>;
|
|
|
} catch {
|
|
|
console.log(`[${i}] JSON 解析失败`);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
const data = body.data as Record<string, unknown> | undefined;
|
|
|
const availableRates = data?.availableRates as
|
|
|
| Record<string, Record<string, unknown>>
|
|
|
| undefined;
|
|
|
|
|
|
const rateCount = availableRates ? Object.keys(availableRates).length : 0;
|
|
|
const legacyRates = body.rates ?? data?.rates;
|
|
|
|
|
|
console.log(`\n[${i}] ${entry.request.method} ${entry.request.url}`);
|
|
|
console.log(" topKeys:", Object.keys(body));
|
|
|
if (data) {
|
|
|
console.log(" dataKeys:", Object.keys(data));
|
|
|
}
|
|
|
console.log(" availableRates count:", rateCount);
|
|
|
console.log(" legacy rates:", legacyRates ? "yes" : "no");
|
|
|
|
|
|
if (availableRates) {
|
|
|
const summary = Object.values(availableRates).map((r) => ({
|
|
|
id: r.id,
|
|
|
serviceLevel: r.serviceLevel,
|
|
|
quoteType: r.quoteType,
|
|
|
serviceType: r.serviceType,
|
|
|
price: r.price ?? r.finalPrice ?? r.baseQuotePrice,
|
|
|
days: r.days,
|
|
|
}));
|
|
|
console.log(" rates sample:", JSON.stringify(summary.slice(0, 8), null, 2));
|
|
|
if (summary.length > 8) {
|
|
|
console.log(` ... +${summary.length - 8} more`);
|
|
|
}
|
|
|
|
|
|
const byLevel = new Map<string, number>();
|
|
|
for (const r of Object.values(availableRates)) {
|
|
|
const key = `${r.serviceLevel}/${r.quoteType ?? r.serviceType ?? "?"}`;
|
|
|
byLevel.set(key, (byLevel.get(key) ?? 0) + 1);
|
|
|
}
|
|
|
console.log(" groupBy serviceLevel/quoteType:", Object.fromEntries(byLevel));
|
|
|
}
|
|
|
}
|