- Introduced a new optional field `registeredOn` to the asset input schema. - Updated asset values and persistence layers to handle the new field. - Enhanced tests to validate the behavior of the `registeredOn` field, including various date formats and null values. - Modified UI components to display the registration date in asset details and forms. - Added localization support for the new field in English and Spanish. - Implemented helper functions for formatting the registration date. - Created integration tests for reading and writing assets with the new field in the database.
49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
export type HttpErrorDiagnostic = Readonly<{
|
|
name: string;
|
|
code?: string;
|
|
errno?: number;
|
|
sqlState?: string;
|
|
frames: readonly string[];
|
|
}>;
|
|
|
|
/** Extrae datos técnicos sin serializar mensajes, SQL ni propiedades arbitrarias del error. */
|
|
export function httpErrorDiagnostics(failure: unknown): readonly HttpErrorDiagnostic[] {
|
|
const diagnostics: HttpErrorDiagnostic[] = [];
|
|
const visited = new Set<Error>();
|
|
let current = failure;
|
|
|
|
while (current instanceof Error && !visited.has(current) && diagnostics.length < 5) {
|
|
visited.add(current);
|
|
diagnostics.push(describeError(current));
|
|
current =
|
|
current.cause instanceof Error
|
|
? current.cause
|
|
: "parent" in current
|
|
? current.parent
|
|
: undefined;
|
|
}
|
|
|
|
return diagnostics.length ? diagnostics : [{ name: "NonErrorThrown", frames: [] }];
|
|
}
|
|
|
|
function describeError(failure: Error): HttpErrorDiagnostic {
|
|
const code = "code" in failure ? failure.code : undefined;
|
|
const errno = "errno" in failure ? failure.errno : undefined;
|
|
const sqlState = "sqlState" in failure ? failure.sqlState : undefined;
|
|
// El prefijo puede contener un mensaje multilínea: se elimina completo antes de leer los frames.
|
|
const prefix = failure.message ? `${failure.name}: ${failure.message}` : failure.name;
|
|
const stack = failure.stack?.startsWith(prefix) ? failure.stack.slice(prefix.length) : "";
|
|
|
|
return {
|
|
name: /^[A-Za-z][A-Za-z0-9]*Error$|^Error$/.test(failure.name) ? failure.name : "Error",
|
|
...(typeof code === "string" && /^(?:ER_[A-Z0-9_]+|E[A-Z0-9_]+)$/.test(code) ? { code } : {}),
|
|
...(typeof errno === "number" && Number.isSafeInteger(errno) ? { errno } : {}),
|
|
...(typeof sqlState === "string" && /^[0-9A-Z]{5}$/.test(sqlState) ? { sqlState } : {}),
|
|
frames: stack
|
|
.split("\n")
|
|
.filter((line) => /^\s+at .+:\d+:\d+\)?$/.test(line))
|
|
.slice(0, 20)
|
|
.map((line) => line.trim()),
|
|
};
|
|
}
|