```markdown
# szs-next-api-debugger 📡

A powerful, floating visual API debugger for **Next.js App Router** and **`openapi-fetch`**. 

Tired of digging through your terminal to find SSR network requests, or trying to match them up with client-side calls in the browser network tab? This package bridges the gap. It intercepts `openapi-fetch` calls, correlates them across the async boundary, and displays **both SSR and Client requests** in a sleek, floating UI directly in your browser.

## ✨ Features

* **SSR + CSR in one place:** See requests made by Server Components alongside Client Components.
* **Production Safe:** Toggle everything via a single `enabled` flag (defaults to `NODE_ENV === 'development'`). When disabled, the overlay renders `null`, the interceptor is inert (no `Request` proxy, no global state), and the SSR route responds with `404`.
* **CORS Safe:** Uses in-memory correlation instead of custom HTTP headers to avoid triggering CORS preflight errors.
* **Smart Stack Traces:** Captures the exact file and line number of the component/hook that initiated the request, filtering out Next.js/Webpack noise.
* **Custom Filters:** Filter by URL substrings or RegEx so you only track what you care about.

## 📦 Installation

```bash
npm install szs-next-api-debugger
# or
yarn add szs-next-api-debugger
# or
pnpm add szs-next-api-debugger

```

> **Note:** This library requires `next`, `react`, `openapi-fetch`, and `zustand` as peer dependencies.

---

## 🚀 Quick Setup (4 simple steps)

### 1. Configure Tailwind CSS

The floating UI is built with Tailwind CSS. To ensure the styles are compiled correctly, add the package to your `tailwind.config.ts` (or `.js`) `content` array:

```javascript
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    // Add this line so Tailwind parses the debugger's UI:
    './node_modules/szs-next-api-debugger/dist/**/*.{js,mjs}',
  ],
  // ...
}

```

### 2. Add the SSR Bridge (API Route)

To stream Server-Side requests to the browser UI, create a route handler using the `createApiDebuggerRouteHandler` factory.
Create a file at `src/app/api/dev/api-debugger/route.ts`:

```typescript
// src/app/api/dev/api-debugger/route.ts
import { createApiDebuggerRouteHandler } from 'szs-next-api-debugger';

export const { GET, DELETE } = createApiDebuggerRouteHandler({
  enabled: true /* or your custom condition */,
});

```

The `enabled` option is optional — when omitted, it defaults to
`process.env.NODE_ENV === 'development'`. When `enabled` is falsy, both `GET`
and `DELETE` respond with `404`, so the route is safe to leave mounted in
production.

### 3. Connect the Interceptor to `openapi-fetch`

Wrap your API client initialization with the `createDebugInterceptor`.

```typescript
// src/api/client.ts
import createClient from 'openapi-fetch';
import { createDebugInterceptor } from 'szs-next-api-debugger';
import type { paths } from './my-openapi-schema';

export const client = createClient<paths>({ baseUrl: '[https://api.example.com](https://api.example.com)' });

client.use(
  createDebugInterceptor({
    // Explicitly toggle the debugger. When omitted, defaults to
    // `process.env.NODE_ENV === 'development'`. When `false`, the interceptor
    // installs an inert middleware and never patches the global `Request`
    // constructor — so nothing leaks into production bundles.
    enabled: process.env.NODE_ENV === 'development',
    position: 'bottom-right',
    // When `true` (default), the client-side request log is wiped on every
    // full page reload so you start each session with a clean slate. Set to
    // `false` to persist logs across reloads via `sessionStorage`.
    clearOnReload: true,
    // Optional: Filter only specific endpoints
    // urlFilters: ['/users', '/cart'],
  })
);

```

### 4. Mount the Overlay in your Layout

Drop the `<ApiDebuggerOverlay />` into your root `layout.tsx`. It will only render in development.

```tsx
// src/app/layout.tsx
import { ApiDebuggerOverlay } from 'szs-next-api-debugger';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        {/* Only active in NODE_ENV === 'development' */}
        <ApiDebuggerOverlay/>
      </body>
    </html>
  );
}

```

---

## ⚙️ Configuration

You can pass a configuration object to `createDebugInterceptor(config)`:

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `enabled` | `boolean` | `process.env.NODE_ENV === 'development'` | Master switch. When `false`, the interceptor becomes a no-op middleware, the `Request` proxy is never installed, and `<ApiDebuggerOverlay />` renders `null`. Pair it with the same value passed to `createApiDebuggerRouteHandler` for a leak-free production build. |
| `position` | `'bottom-left' \| 'bottom-right'` | `'bottom-right'` | Placement of the floating badge and panel. |
| `urlFilters` | `Array<string \| RegExp>` | `[]` | Only log requests matching these substrings/regexes. Empty array logs everything. |
| `maxRequests` | `number` | `100` | Max number of requests to retain in memory (per environment) before dropping old ones. |
| `clearOnReload` | `boolean` | `true` | When `true`, the persisted client-side request list is cleared on every full page reload. When `false`, requests survive reloads within the same tab via `sessionStorage`. |
| `logToConsole` | `boolean` | `false` | Emit a collapsed `console.trace` group for every intercepted request. Useful for hooking into Chrome's async stack stitching. |

---

## 🛠 How it works under the hood

Next.js App Router isolates Server and Client memory.

1. **Server Requests:** Intercepted and stored in `globalThis` (surviving HMR).
2. **Client Requests:** Intercepted and stored in a local Zustand store.
3. **The Bridge:** The UI component polls the `/api/dev/api-debugger` route every 1000ms to fetch the latest Server requests and merges them seamlessly with Client requests into a unified chronological view.

## 🤝 Contributing

Issues and Pull Requests are welcome!