Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/build/buildWarningTriage.ts
T

117 lines
3.7 KiB
TypeScript

export type BuildWarningInput = {
code?: string | null;
message?: string | null;
id?: string | null;
file?: string | null;
};
export type BuildWarningClass =
| "large-chunk"
| "empty-chunk"
| "production-sourcemap"
| "aws-smithy-circular-chunk"
| "dynamic-static-import"
| "sourcemap-resolve-failure"
| "next-themes-invalid-annotation"
| "unknown";
export type BuildWarningClassification = {
class: BuildWarningClass;
suppressed: boolean;
code?: string;
message: string;
id?: string;
file?: string;
};
const normalize = (value: string | null | undefined) => value?.toLowerCase() ?? "";
const EMPTY_CHUNK_ALLOWLIST = new Set([
"___entity.export",
"api.collab.token",
"api.embed.forms._formKey.submit",
"api.leads.capture",
"api.metrics",
"api.password-policy-remind",
"api.status",
"api.tenants._tenant.plugins",
"callback",
"dry-run",
"healthcheck",
"healthz",
"ip-address-log-labels",
"logout",
"null",
"onboarding._id",
"postman_collection_._json",
"preferences",
"readyz",
"start",
"stream",
"submit",
"swagger",
"track-click._deliveryId",
"track-open._deliveryId_.gif_",
"workflows._id.run.stream._executionId",
]);
function getEmptyChunkName(message: string): string | null {
const match = /generated an empty chunk:\s*["']?([^"'.]+(?:\.[^"'.]+)*)["']?/i.exec(message);
return match?.[1] ?? null;
}
export function classifyBuildWarning(warning: BuildWarningInput): BuildWarningClassification {
const code = warning.code ?? undefined;
const message = warning.message ?? "";
const id = warning.id ?? undefined;
const file = warning.file ?? undefined;
const normalizedCode = normalize(code);
const normalizedMessage = normalize(message);
const normalizedId = normalize(id);
let warningClass: BuildWarningClass = "unknown";
if (
normalizedMessage.includes("some chunks are larger than") ||
normalizedMessage.includes("chunk size limit") ||
normalizedMessage.includes("chunk size warning")
) {
warningClass = "large-chunk";
} else if (normalizedMessage.includes("generated an empty chunk") || normalizedMessage.includes("empty chunk")) {
warningClass = "empty-chunk";
} else if (normalizedMessage.includes("source maps are enabled in production")) {
warningClass = "production-sourcemap";
} else if (
normalizedMessage.includes("will end up in different chunks") &&
normalizedMessage.includes("circular dependency between chunks") &&
(normalizedMessage.includes("@aws-sdk") || normalizedMessage.includes("@smithy"))
) {
warningClass = "aws-smithy-circular-chunk";
} else if (
normalizedMessage.includes("is dynamically imported by") &&
normalizedMessage.includes("but also statically imported by") &&
normalizedMessage.includes("dynamic import will not move module into another chunk")
) {
warningClass = "dynamic-static-import";
} else if (normalizedCode === "sourcemap_error" && normalizedMessage.includes("can't resolve original location")) {
warningClass = "sourcemap-resolve-failure";
} else if (normalizedCode === "invalid_annotation" && normalizedId.includes("next-themes")) {
warningClass = "next-themes-invalid-annotation";
}
const emptyChunkName = warningClass === "empty-chunk" ? getEmptyChunkName(message) : null;
const suppressEmptyChunk = emptyChunkName !== null && EMPTY_CHUNK_ALLOWLIST.has(emptyChunkName);
return {
class: warningClass,
suppressed: suppressEmptyChunk || warningClass === "sourcemap-resolve-failure" || warningClass === "next-themes-invalid-annotation",
code,
message,
id,
file,
};
}
export function shouldSuppressBuildWarning(warning: BuildWarningInput): boolean {
return classifyBuildWarning(warning).suppressed;
}