Installation
npm install @squasher/node
Setup
Initialize at the top of your entry file, before other imports:
import { init } from "@squasher/node";
init({
apiKey: process.env.SQUASHER_API_KEY!,
projectId: process.env.SQUASHER_PROJECT_ID!,
environment: process.env.NODE_ENV,
});
init() registers handlers for process.on('uncaughtException') and process.on('unhandledRejection') automatically.
Framework Integration
Express
Fastify
Hono
Plain Node.js
import express from "express";
import { captureError } from "@squasher/node";
const app = express();
app.get("/api/users", async (req, res, next) => {
try {
res.json(await db.getUsers());
} catch (error) {
next(error);
}
});
// Add AFTER all routes
app.use(async (err: unknown, req: express.Request, res: express.Response, _next: express.NextFunction) => {
if (err instanceof Error) {
await captureError(err, { url: req.originalUrl, method: req.method });
}
res.status(500).json({ error: "Internal server error" });
});
import Fastify from "fastify";
import { captureError } from "@squasher/node";
const app = Fastify();
app.setErrorHandler(async (error, request, reply) => {
await captureError(error, { url: request.url, method: request.method });
reply.status(500).send({ error: "Internal server error" });
});
import { Hono } from "hono";
import { captureError } from "@squasher/node";
const app = new Hono();
app.onError(async (err, c) => {
await captureError(err, { url: c.req.url, method: c.req.method });
return c.json({ error: "Internal server error" }, 500);
});
import { captureError } from "@squasher/node";
try {
await processPayment(order);
} catch (error) {
await captureError(error as Error, { orderId: order.id });
}
Manual Capture
import { captureError, captureMessage } from "@squasher/node";
await captureError(new Error("Payment failed"), { orderId: "ord_123" });
await captureMessage("Worker started", "info");
await captureMessage("Queue depth exceeds 1000", "warning");
User Context & Breadcrumbs
import { getClient } from "@squasher/node";
getClient().setUser({ id: user.id, email: user.email });
getClient().addBreadcrumb({ category: "auth", message: "User logged in" });
getClient().addBreadcrumb({ category: "db", message: "SELECT * FROM orders" });
// Last 50 breadcrumbs are included in the next error
beforeSend
init({
apiKey: process.env.SQUASHER_API_KEY!,
projectId: process.env.SQUASHER_PROJECT_ID!,
beforeSend: (event) => {
if (event.request?.url?.includes("/health")) return null; // drop noise
delete event.extra?.password; // scrub PII
return event;
},
});
Runtime Compatibility
| Runtime | Status |
|---|
| Node.js 18+ | Supported |
| Node.js 20+ LTS | Recommended |
| Bun | Supported |
| Deno | Untested (should work via npm:) |
Uses standard fetch with no native dependencies.
Configuration
| Option | Type | Default | Description |
|---|
apiKey | string | Required | Project API key (sq_pk_...) |
projectId | string | Required | Project ID |
endpoint | string | https://ingest.squasher.ai | Ingestion endpoint |
environment | string | — | Environment tag |
release | string | — | Release version |
sampleRate | number | 1 | Sample rate 0-1 |
debug | boolean | false | Log to console |
beforeSend | function | — | Filter/modify events |