@laigma/logger
v1.0.1
Published
Logger utility for back/front apps
Maintainers
Readme
@laigma's logger
A lightweight logging library for Node.js and browser apps
📋 Overview
@laigma/logger is a lightweight logging library with four independent plugins:
| Plugin | Target | Purpose |
|---|---|---|
| createBackendLogger | Node.js | Colorized dev logs + structured JSON for production |
| createBackendApiLogger | Node.js | Axios interceptor that logs HTTP requests/responses |
| createFrontendLogger | Browser | Styled console.debug logs via CSS %c |
| createFrontendApiLogger | Browser | Axios interceptor that logs HTTP requests/responses |
🚀 Installation
npm install @laigma/loggeryarn add @laigma/loggerpnpm add @laigma/logger🖥️ Backend output preview
Dev mode — colorized ANSI, human-readable:
*** Something went wrong ***
Error: disk full
*** Record saved successfully ***
{"id":42,"name":"item"}
*** Retrying connection... ***
{"attempt":3,"maxRetries":5}
*** Server started ***
3/6/2026, 13:40:40Dev mode — API interceptor:
*** ✔ SUCCESS - /v1 ***
[GET] https://api.example.com/v1/users
Payload: {"page":1}
Status: 200 | Duration: 85 ms | Response size: 28 bytes
Response: {"userId":42,"name":"Alice"}
*** ✖ ERROR - /v1 ***
[GET] https://api.example.com/v1/products/999
Payload: null
Status: 404 | Duration: 55 ms
Message: Request failed with status code 404
Details: {"error":"Product not found"}Production mode — structured JSON per line:
{"appName":"demo-app","appVersion":"1.0.0","level":"ERROR","message":"Auth failure","detail":{"name":"Error","message":"invalid token"},"metadata":{"category":"auth","scope":"login","level":"CRITICAL"},"timestamp":"2026-03-06T12:40:41.223Z"}
{"appName":"demo-app","appVersion":"1.0.0","level":"SUCCESS","message":"Order placed","detail":{"orderId":"ORD-001","total":99.99},"metadata":null,"timestamp":"2026-03-06T12:40:41.224Z"}
{"appName":"demo-app","appVersion":"1.0.0","level":"WARNING","message":"High memory usage","detail":{"usedMb":780,"limitMb":1024},"metadata":{"category":"system","scope":"memory","level":"HIGH"},"timestamp":"2026-03-06T12:40:41.224Z"}🌐 Frontend output preview
Frontend logs use the browser DevTools console.debug with %c CSS styling. Each level has a distinct color, and object details are rendered as interactive expandable trees.
*** Something went wrong *** ← red on #ffe6e6
*** Record saved successfully *** ← green on #e6ffe6
*** Watch out *** ← orange on #fffbe6
*** App initialized *** ← purple on #f3e6ff
3/6/2026, 13:40:40Frontend API interceptor — success and error details appear as expandable objects in DevTools:
*** ✔ SUCCESS - /v1 ***
▶ { method: "GET", url: "…", statusCode: 200, duration: 85, responseSize: 28, response: {…}, params: {…} }
*** ✖ ERROR - /v1 ***
▶ { method: "GET", url: "…", statusCode: 404, errorMessage: "…", errorDetails: {…}, duration: 55, params: null }📖 Usage
BackendLogger
Structured logger for Node.js services. Supports two output modes controlled by envMode.
import { createBackendLogger } from "@laigma/logger";
const logger = createBackendLogger({
envMode: "development", // "production" switches to structured JSON output
appName: "my-app",
appVersion: "1.0.0",
});BackendLoggerConfig
| Property | Type | Default | Description |
|---|---|---|---|
| envMode | string | — | "production" enables JSON output; any other value uses colorized ANSI |
| appName | string | "unknown" | Included in every production log entry |
| appVersion | string | "unknown" | Included in every production log entry |
Methods
| Method | Signature | Notes |
|---|---|---|
| logError | (message, errorObj, metadata, stopProcess?) | errorObj and metadata required — all LogMetadata fields must be present. Pass stopProcess: true to call process.exit(1). |
| logWarning | (message, detailObj, metadata) | detailObj and metadata required — all LogMetadata fields must be present. |
| logSuccess | (message, detailObj?, metadata?) | All extra params optional. LogMetadata fields are optional. |
| logInfo | (message, metadata?) | metadata optional. LogMetadata fields are optional. Appends a timestamp automatically. |
| logProgressBar | (processed, total, message) | Renders an inline progress bar to stdout. |
LogMetadata
All fields are required when passed to logError or logWarning (Required<LogMetadata>). All fields are optional when passed to logInfo or logSuccess.
{
category: string; // e.g. "auth", "api", "storage"
scope: string; // e.g. "login", "http", "upload"
level: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
}When metadata is omitted (allowed on logInfo/logSuccess), the production JSON output will contain "metadata": null. Only the fields you provide are included.
Examples
logger.logError("Auth failed", new Error("invalid token"), { category: "auth", scope: "login", level: "CRITICAL" });
logger.logWarning("High memory", { usedMb: 780 }, { category: "system", scope: "memory", level: "HIGH" });
logger.logSuccess("Order placed", { orderId: "ORD-001" });
logger.logInfo("Server started");
// progress bar — call on every iteration
for (let i = 1; i <= total; i++) {
logger.logProgressBar(i, total, "Importing records");
}BackendApiLogger
Attaches Axios request/response interceptors to automatically log all HTTP calls. Requires a BackendLogger instance.
import { createBackendLogger, createBackendApiLogger } from "@laigma/logger";
const logger = createBackendLogger({
envMode: process.env.NODE_ENV,
appName: "my-app",
appVersion: "1.0.0",
});
const apiLogger = createBackendApiLogger(
logger,
process.env.NODE_ENV,
{ category: "api", scope: "http", level: "LOW" }, // optional, these are the defaults
);
apiLogger.attachLoggerInterceptors(axiosInstance);Parameters
| Parameter | Type | Description |
|---|---|---|
| logger | BackendLogger | An instance created with createBackendLogger |
| envMode | string | Controls dev vs production detail format (should match the logger's envMode) |
| metadata | LogMetadata | Optional. Attached to every logError call. Defaults to { category: "api", scope: "http", level: "LOW" } |
Behavior
- A request interceptor stamps
config.metadata.startTimeon every outgoing request to measure duration. - Successful responses call
logSuccesswith method, URL, status, duration, response size, and body.- Dev mode: formatted ANSI string.
- Production mode: plain object.
- Error responses call
logErrorwith method, URL, status, error message, error details, and duration, plus themetadatapassed at construction time.- Dev mode: formatted ANSI string.
- Production mode: plain object.
FrontendLogger
Browser logger using styled console.debug calls. Each level renders with a distinct CSS badge in DevTools.
import { createFrontendLogger } from "@laigma/logger";
const logger = createFrontendLogger({
onError: (message) => alertError(message), // optional
});FrontendLoggerConfig
| Property | Type | Description |
|---|---|---|
| onError | (message: string) => void | Optional callback invoked when logError is called with stopProcess = true |
Methods
| Method | Signature | Notes |
|---|---|---|
| logError | (message, errorObj?, stopProcess?) | All params after message optional. Pass stopProcess: true to trigger the onError callback. |
| logWarning | (message, detailObj?) | — |
| logSuccess | (message, detailObj?) | — |
| logInfo | (message, detailObj?) | If no detailObj is provided, appends a timestamp automatically. |
Object details are passed as a third argument to console.debug so DevTools renders them as an expandable tree. String/primitive details are emitted in a second console.debug call.
Examples
logger.logError("Auth failed", error, true); // triggers onError
logger.logWarning("Slow response", { ms: 4200 });
logger.logSuccess("Profile saved", { userId: 7 });
logger.logInfo("App initialized"); // auto-appends timestamp
logger.logInfo("Route changed", { path: "/home" }); // uses provided detailFrontendApiLogger
Attaches Axios request/response interceptors for browser apps. Requires a FrontendLogger instance. Detail objects are logged as interactive trees in DevTools — no string formatting, no envMode needed.
import { createFrontendLogger, createFrontendApiLogger } from "@laigma/logger";
const logger = createFrontendLogger({
onError: (msg) => alertError(msg),
});
const apiLogger = createFrontendApiLogger(logger);
apiLogger.attachLoggerInterceptors(axiosInstance);Parameters
| Parameter | Type | Description |
|---|---|---|
| logger | FrontendLogger | An instance created with createFrontendLogger |
Behavior
- A request interceptor stamps
config.metadata.startTimeon every outgoing request to measure duration. - Successful responses call
logSuccesswith an object containing:method,url,params,statusCode,duration(ms),responseSize(bytes),response. - Error responses call
logErrorwith an object containing:method,url,params,statusCode,errorMessage,errorDetails,duration(ms).
Success detail shape
{
method: string; // "GET", "POST", …
url: string; // full URL (baseURL + url)
params: unknown; // request params or body
statusCode: number; // e.g. 200
duration: number | null; // ms from request start, null if unavailable
responseSize: number; // serialized response byte length
response: unknown; // response body
}Error detail shape
{
method: string;
url: string;
params: unknown;
statusCode: number; // defaults to 500 if no response object
errorMessage: string;
errorDetails: unknown; // response body, null if unavailable
duration: number | null;
}