@bamboo-studio/error-management
v0.0.4
Published
Typed, extensible error management for Node.js TypeScript projects
Downloads
416
Readme
@bamboo-studio/error-management
Typed, extensible error management for Node.js TypeScript projects.
- Caller automatico — il nome della funzione che ha lanciato l'errore viene rilevato dallo stack V8, senza doverlo specificare
- Codici estendibili — aggiungi codici custom e sovrascrivi quelli base con
createErrorCodes() - Errori estendibili — crea subclass senza boilerplate con
defineError() - Error chaining — propaga la causa originale (
cause) attraverso tutta la catena - Serializzazione JSON —
toJSON()pronto per logger strutturati (Pino, Winston…)
Installazione
npm install @bamboo-studio/error-managementUtilizzo base
import { AppError, isAppError } from "@bamboo-studio/error-management";
function processOrder(id: string) {
if (!id) throw new AppError("Order ID mancante", "INVALID_ARGUMENT");
}
try {
processOrder("");
} catch (err) {
if (isAppError(err)) {
console.log(err.toString());
// → [INVALID_ARGUMENT] AppError in processOrder(): Order ID mancante
console.log(err.caller); // → processOrder
console.log(err.code); // → INVALID_ARGUMENT
}
}Estendere i codici di errore
Usa createErrorCodes() per aggiungere codici custom ai codici base della libreria.
Il tipo risultante è la fusione completa — autocompletamento garantito.
import { createErrorCodes } from "@bamboo-studio/error-management";
export const ErrorCode = createErrorCodes({
PAYMENT_FAILED: "PAYMENT_FAILED",
SUBSCRIPTION_EXPIRED: "SUBSCRIPTION_EXPIRED",
// Puoi anche sovrascrivere un codice base
INTERNAL: "MY_INTERNAL",
});
// Esporta il tipo per usarlo nelle firme di funzione
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];Creare errori custom
Con defineError() — zero boilerplate
import { defineError } from "@bamboo-studio/error-management";
import { ErrorCode } from "./errorCodes";
export const PaymentError = defineError(
"PaymentError",
ErrorCode.PAYMENT_FAILED,
);
export const SubscriptionError = defineError(
"SubscriptionError",
ErrorCode.SUBSCRIPTION_EXPIRED,
);
// Utilizzo
throw new PaymentError("Carta rifiutata");
// → [PAYMENT_FAILED] PaymentError in chargeCard(): Carta rifiutataCon defineError() + campi extra
import { defineError, AppErrorOptions } from "@bamboo-studio/error-management";
const _InvoiceBase = defineError("InvoiceError", "INVOICE_ERROR");
export class InvoiceError extends _InvoiceBase {
constructor(
message: string,
public readonly invoiceId: string,
options: AppErrorOptions = {},
) {
super(message, undefined, {
...options,
callerSkip: (options.callerSkip ?? 0) + 1,
});
}
override toJSON() {
return { ...super.toJSON(), invoiceId: this.invoiceId };
}
}
// Utilizzo
throw new InvoiceError("Fattura non trovata", "INV-2025-001");Estendendo direttamente AppError
import { AppError, AppErrorOptions } from "@bamboo-studio/error-management";
export class ValidationError extends AppError {
constructor(
message: string,
public readonly fields: Record<string, string>,
options: AppErrorOptions = {},
) {
super(message, "VALIDATION", {
...options,
callerSkip: (options.callerSkip ?? 0) + 1,
});
}
override toJSON() {
return { ...super.toJSON(), fields: this.fields };
}
}wrapError — wrapping di errori nativi
Converte qualsiasi unknown (catch clause) in un AppError. Se è già un AppError, lo restituisce as-is senza double-wrapping.
import { wrapError } from "@bamboo-studio/error-management";
import { ErrorCode } from "./errorCodes";
async function fetchData(url: string) {
try {
return await fetch(url).then((r) => r.json());
} catch (err) {
throw wrapError(err, ErrorCode.NETWORK, `Impossibile contattare ${url}`);
}
}tryCatch — async shorthand
import { tryCatch } from "@bamboo-studio/error-management";
import { ErrorCode } from "./errorCodes";
const data = await tryCatch(
() => fetch("https://api.example.com").then((r) => r.json()),
ErrorCode.NETWORK,
"Impossibile recuperare i dati",
);Type guards
import { isAppError, isErrorCode } from "@bamboo-studio/error-management";
import { ErrorCode } from "./errorCodes";
try {
await chargeCard(userId);
} catch (err) {
if (isErrorCode(err, ErrorCode.PAYMENT_FAILED)) {
// err è tipizzato come AppError & { code: 'PAYMENT_FAILED' }
await notifyUser(userId);
} else if (isAppError(err)) {
logger.error(err.toJSON());
} else {
throw err; // rilancia se non è un AppError
}
}Errori predefiniti
Importabili direttamente, pronti all'uso:
| Classe | Codice |
| ------------------- | -------------- |
| ValidationError | VALIDATION |
| NotFoundError | NOT_FOUND |
| UnauthorizedError | UNAUTHORIZED |
| ForbiddenError | FORBIDDEN |
| DatabaseError | DATABASE |
| NetworkError | NETWORK |
| TimeoutError | TIMEOUT |
AppError — proprietà
| Proprietà | Tipo | Descrizione |
| --------- | --------- | ---------------------------------------- |
| message | string | Messaggio leggibile dall'utente |
| code | string | Codice leggibile dalla macchina |
| caller | string | Funzione che ha lanciato l'errore (auto) |
| cause | unknown | Errore originale wrappato |
| stack | string | Stack trace |
| name | string | Nome della classe (PaymentError, ecc.) |
Pubblicazione
npm run build
npm publish