# bugfixes

> TypeScript logging, error tracking, and HTTP middleware library for Bugfixes

Latest version **2.3.2** (published 2026-09-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install bugfixes
pnpm add bugfixes
yarn add bugfixes
bun add bugfixes
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.3.2 |
| Published | 2026-09-23 |
| First published | 2018-01-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=24.0.0 |
| Dependencies | 0 |
| Unpacked size | 119.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Maintainers | keloran |
| Keywords | bugfixes, logging, middleware, error-tracking |

## Links

- npm: https://www.npmjs.com/package/bugfixes
- Repository: https://github.com/BugFixes/ts-bugfixes
- Homepage: https://github.com/BugFixes/ts-bugfixes#readme
- Issues: https://github.com/BugFixes/ts-bugfixes/issues
- npm.io page: https://npm.io/package/bugfixes

## Alternatives

- [@sentry/react-native](https://npm.io/package/@sentry/react-native.md) — 2.6M weekly downloads
- [@ardatan/aggregate-error](https://npm.io/package/@ardatan/aggregate-error.md) — 708.1K weekly downloads
- [custom-error-generator](https://npm.io/package/custom-error-generator.md) — 2.0K weekly downloads
- [@technik-sde/prosemirror-recreate-transform](https://npm.io/package/@technik-sde/prosemirror-recreate-transform.md) — 1.5K weekly downloads
- [@suchipi/error-utils](https://npm.io/package/@suchipi/error-utils.md) — 78 weekly downloads

## Recent versions

- 2.3.2 (latest) — 2026-09-23
- 2.2.0 — 2026-03-17
- 2.0.0 — 2026-03-17
- 1.7.0 — 2018-04-19
- 1.6.2 — 2018-04-10
- 1.6.1 — 2018-04-09
- 1.6.0 — 2018-04-09
- 1.5.0 — 2018-03-20
- 1.4.1 — 2018-03-14
- 1.4.0 — 2018-03-11
- 1.3.0 — 2018-03-06
- 1.2.1 — 2018-03-06
- 1.2.0 — 2018-02-12
- 1.1.0 — 2018-02-06
- 1.0.2 — 2018-01-26
- … 2 more at https://npm.io/package/bugfixes/versions

## README

# bugfixes

TypeScript logging, error reporting, and HTTP middleware. Works in Node.js, browsers, and Edge Runtime with **zero runtime dependencies**.

ESM-first with named exports from the package root.

## Install

```bash
npm install bugfixes
```

Node 24+ is required for server-side usage. Browser and Edge Runtime are supported out of the box.

## What It Exports

| Subpath | Environment | Description |
|---|---|---|
| `bugfixes` | All | Logging, config, stack traces, icons, utilities |
| `bugfixes/logs` | All | Logging-only subset |
| `bugfixes/middleware` | Node.js | HTTP middleware for `node:http` servers |

## Configuration

Environment variables (server-side only):

```bash
BUGFIXES_AGENT_KEY=your-key
BUGFIXES_AGENT_SECRET=your-secret
BUGFIXES_AGENT_ID=your-agent-id
BUGFIXES_SERVER=https://api.bugfix.es/v1
BUGFIXES_LOG_LEVEL=warn
BUGFIXES_LOCAL_ONLY=false
BUGFIXES_ICON_SKIP=false
BUGFIXES_COMMIT_SHA=full-git-object-id
BUGFIXES_RELEASE=checkout-api@2.4.0
BUGFIXES_ENVIRONMENT=development
```

Legacy aliases `BUGFIXES_KEY`, `BUGFIXES_SECRET`, and `BUGFIXES_ID` are also accepted.

Apply environment config explicitly:

```ts
import { loadConfigFromEnv, setDefaultConfig } from "bugfixes";

setDefaultConfig(loadConfigFromEnv());
```

Or configure directly (works in any environment):

```ts
import { setDefaultConfig } from "bugfixes";

setDefaultConfig({
  agentKey: "your-key",
  agentSecret: "your-secret",
  localOnly: false,
  commitSha: "full-git-object-id",
  release: "checkout-api@2.4.0",
  environment: "development",
});
```

Commit, release, and environment are optional event metadata. The SDK reads only the
explicit `BUGFIXES_*` values above; it does not guess from `NODE_ENV`, Git, or a CI
provider. Set them from deployment configuration when you want them reported.

Remote reporting only happens when `localOnly` is false and both `agentKey` and `agentSecret` are set.

## Logging

```ts
import { log, info, warn, debug, error, fatal } from "bugfixes";

log("server boot");
info("listening on port", 3000);
warn("deprecated route");
debug("payload", JSON.stringify({ ok: true }));

const err = error("database unavailable");
// error() returns an Error object

fatal("unrecoverable"); // exits process in Node, throws in browser/Edge
```

Return values:

- `log`, `info`, `warn`, `debug` return formatted strings like `[INFO]: server started`
- `error` returns an `Error` with a captured stack trace
- `fatal` exits the process (Node) or throws (browser/Edge)

### Instance-level config

```ts
import { BugFixes } from "bugfixes";

const logger = new BugFixes().setConfig({
  agentKey: "your-key",
  agentSecret: "your-secret",
  localOnly: true,
});

logger.logAt("info", "configured logger");
```

### Local-only logging

```ts
import { local } from "bugfixes";

const logger = local();
logger.logAt("warn", "local warning only");
```

## Next.js

### Server Components and API Routes

```ts
// app/api/orders/route.ts
import { info, error } from "bugfixes";

export async function GET() {
  info("fetching orders");
  try {
    const orders = await db.order.findMany();
    return Response.json(orders);
  } catch (err) {
    error("failed to fetch orders", err);
    return Response.json({ error: "Internal Server Error" }, { status: 500 });
  }
}
```

### Server Actions

```ts
// app/actions.ts
"use server";

import { info, error } from "bugfixes";

export async function createOrder(formData: FormData) {
  const name = formData.get("name") as string;
  info("creating order", name);

  try {
    const order = await db.order.create({ data: { name } });
    return { success: true, id: order.id };
  } catch (err) {
    const e = error("order creation failed", err);
    return { success: false, error: e.message };
  }
}
```

### Client Components

```ts
// components/checkout.tsx
"use client";

import { info, error } from "bugfixes";

export function Checkout() {
  const handleSubmit = async () => {
    info("checkout started");
    try {
      await submitOrder();
      info("checkout complete");
    } catch (err) {
      error("checkout failed", err);
    }
  };

  return <button onClick={handleSubmit}>Place Order</button>;
}
```

### Next.js Middleware (Edge Runtime)

```ts
// middleware.ts
import { info } from "bugfixes";
import { NextResponse } from "next/server";

export function middleware(request: Request) {
  info("request", request.method, new URL(request.url).pathname);
  return NextResponse.next();
}
```

### Setup with instrumentation

```ts
// instrumentation.ts
import { loadConfigFromEnv, setDefaultConfig } from "bugfixes";

export function register() {
  setDefaultConfig(loadConfigFromEnv());
}
```

## TanStack Start

### Server Functions

```ts
// app/server/orders.ts
import { createServerFn } from "@tanstack/start";
import { info, error } from "bugfixes";

export const getOrders = createServerFn().handler(async () => {
  info("fetching orders");
  try {
    return await db.order.findMany();
  } catch (err) {
    error("failed to fetch orders", err);
    throw err;
  }
});

export const createOrder = createServerFn()
  .validator((data: { name: string }) => data)
  .handler(async ({ data }) => {
    info("creating order", data.name);
    try {
      return await db.order.create({ data });
    } catch (err) {
      error("order creation failed", err);
      throw err;
    }
  });
```

### Route Components

```tsx
// app/routes/orders.tsx
import { createFileRoute } from "@tanstack/react-router";
import { info } from "bugfixes";
import { getOrders } from "../server/orders";

export const Route = createFileRoute("/orders")({
  loader: async () => {
    info("loading orders route");
    return getOrders();
  },
  component: OrdersPage,
});

function OrdersPage() {
  const orders = Route.useLoaderData();
  return (
    <ul>
      {orders.map((o) => (
        <li key={o.id}>{o.name}</li>
      ))}
    </ul>
  );
}
```

### Client-Side Error Logging

```tsx
// app/routes/__root.tsx
import { createRootRoute, Outlet } from "@tanstack/react-router";
import { error } from "bugfixes";

export const Route = createRootRoute({
  errorComponent: ({ error: err }) => {
    error("unhandled route error", err);
    return <div>Something went wrong</div>;
  },
  component: () => <Outlet />,
});
```

### App Entry Setup

```ts
// app/ssr.tsx or app/client.tsx
import { setDefaultConfig } from "bugfixes";

setDefaultConfig({
  agentKey: import.meta.env.VITE_BUGFIXES_KEY ?? "",
  agentSecret: import.meta.env.VITE_BUGFIXES_SECRET ?? "",
});
```

## HTTP Middleware (Node.js)

For raw `node:http` servers. Import from `bugfixes` or `bugfixes/middleware`.

```ts
import http from "node:http";
import {
  newDefaultMiddleware,
  createCorsMiddleware,
} from "bugfixes";

const system = newDefaultMiddleware();
system.addMiddleware(
  createCorsMiddleware({
    allowedOrigins: ["http://localhost:3000"],
  }),
);

const handler = system.handler((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("ok");
});

http.createServer(handler).listen(3000);
```

Available middleware:

- `requestIdMiddleware` — attach `X-Request-Id` header
- `loggerMiddleware` — log method, path, status, duration, bytes
- `recovererMiddleware` — catch errors, return 500, optionally report to API
- `createRecovererMiddleware(key?, secret?)` — recoverer with credential overrides
- `createCorsMiddleware(options?)` — CORS headers and OPTIONS preflight
- `asyncRecoverer(handler)` — wrap async handlers with error recovery

## Utility Helpers

```ts
import { isDefined } from "bugfixes";

isDefined(null);      // false (narrowed out)
isDefined(undefined); // false (narrowed out)
isDefined("");        // true (narrowed to string)
isDefined(0);         // true (narrowed to number)
```

`isDefined` is a TypeScript type guard that narrows `T | null | undefined` to `T`.

## Icons

Icons are disabled by default. Enable them with:

```ts
import { setIconSkip, withIcon } from "bugfixes";

setIconSkip(false);
withIcon("info", "hello"); // "‼ hello"
```

Or via environment variable: `BUGFIXES_ICON_SKIP=false`.

## Platform Support

The core library (`bugfixes`, `bugfixes/logs`) uses only cross-platform APIs:

- `fetch()` for remote reporting (replaces `node:http`)
- `performance.now()` for timing (replaces `process.hrtime`)
- `crypto.randomUUID()` for IDs (replaces `node:crypto`)
- `crypto.subtle` for JWT signing (replaces `jsonwebtoken`)
- `TextEncoder` for byte length (replaces `Buffer`)
- `console` fallback for output in browsers (replaces `process.stdout`)

The middleware subpath (`bugfixes/middleware`) requires Node.js as it uses `node:http` types.

---
_Source: https://npm.io/package/bugfixes · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
