brakit 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **See what your app is actually doing.**
4
4
 
5
- One command. Every request, query, and security issue — before you ship.
5
+ Every request, query, and security issue — before you ship.
6
6
 
7
7
  Open source · Local only · Zero config · 2 dependencies
8
8
 
@@ -10,25 +10,22 @@ Open source · Local only · Zero config · 2 dependencies
10
10
  [![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
11
11
  [![TypeScript](https://img.shields.io/badge/built%20with-TypeScript-3178c6.svg)](https://typescriptlang.org)
12
12
 
13
- <!-- TODO: Add demo gif showing: npx brakit dev → use app → dashboard shows issues -->
14
- <!-- ![Brakit Demo](assets/demo.gif) -->
15
-
16
13
  ---
17
14
 
18
15
  ## Quick Start
19
16
 
20
17
  ```bash
21
- npx brakit dev
18
+ npx brakit install
22
19
  ```
23
20
 
24
- That's it. Brakit auto-detects your framework, starts your dev server behind a transparent proxy, and serves a live dashboard at `/__brakit`.
21
+ That's it. Brakit detects your framework, adds itself as a devDependency, and creates the instrumentation file. Start your app normally:
25
22
 
26
23
  ```bash
27
- npx brakit dev --port 8080 # Custom proxy port
28
- npx brakit dev --show-static # Include static assets in output
29
- npx brakit dev ./my-app # Specify project directory
24
+ npm run dev
30
25
  ```
31
26
 
27
+ Dashboard at `http://localhost:<port>/__brakit`. Insights in the terminal.
28
+
32
29
  > **Requirements:** Node.js >= 18 and a project with `package.json`.
33
30
 
34
31
  [Documentation](https://brakit.ai/docs) · [Website](https://brakit.ai)
@@ -78,32 +75,33 @@ Developers using AI tools (Cursor, Copilot, Claude Code) to generate API code th
78
75
 
79
76
  ---
80
77
 
81
- ## Principles — ZEAL
82
-
83
- Everything we build is anchored around four pillars:
84
-
85
- | | Pillar | What it means |
86
- |---|---|---|
87
- | **Z** | **Zero Config** | One command to start, zero config by default. Optional middleware for deeper integration — but the default path is always zero-touch. |
88
- | **E** | **Extensible** | Open source. One file, one interface. Add a database adapter, security rule, or language SDK without touching brakit's core. |
89
- | **A** | **AI-Native** | Built for the era where AI writes code humans don't fully review. A safety net for AI-generated APIs. |
90
- | **L** | **Language Agnostic** | HTTP proxy works with any backend. SDK protocol accepts events from any language. Not locked to Node.js. |
91
-
92
- ---
93
-
94
78
  ## How It Works
95
79
 
96
80
  ```
97
- Browser --> Brakit (proxy) --> Your dev server
98
- |
99
- +-- Dashboard UI (/__brakit)
100
- +-- Live SSE stream (real-time updates)
101
- +-- Telemetry (from instrumented process)
81
+ import 'brakit' hooks into http.Server captures everything
82
+ |
83
+ +-- Dashboard UI (/__brakit)
84
+ +-- Live SSE stream (real-time updates)
85
+ +-- Terminal output (insights as you develop)
102
86
  ```
103
87
 
104
- Brakit is a transparent HTTP reverse proxy. Every request passes through unchanged your app works exactly the same. Brakit captures request/response pairs, groups them into actions, and streams everything to the dashboard.
88
+ `import 'brakit'` runs inside your process. It patches `http.Server.prototype.emit` to intercept all requests capturing request/response pairs, grouping them into actions, and streaming everything to the dashboard at `/__brakit` on your existing port. No proxy, no second process, no different port.
89
+
90
+ Instrumentation hooks capture fetch calls, DB queries, console output, and errors automatically — zero code changes.
105
91
 
106
- The instrumentation layer runs inside your dev server process (injected via `--import`) and sends telemetry back to Brakit over a local HTTP connection. That's how fetch calls, queries, and console output get captured without any code changes.
92
+ ### Production Safety
93
+
94
+ Brakit never runs in production. 7 independent layers ensure it:
95
+
96
+ | # | Layer | How it blocks |
97
+ |---|---|---|
98
+ | 1 | `shouldActivate()` | Checks `NODE_ENV` + 15 cloud/CI env vars |
99
+ | 2 | `instrumentation.ts` guard | Its own `NODE_ENV !== 'production'` check |
100
+ | 3 | devDependency | Pruned in production builds |
101
+ | 4 | `try/catch` on import | Missing module = silent no-op |
102
+ | 5 | Localhost-only dashboard | Non-local IPs get 404 on `/__brakit` |
103
+ | 6 | `safeWrap` + circuit breaker | 10 errors = brakit self-disables |
104
+ | 7 | `BRAKIT_DISABLE=true` | Manual kill switch |
107
105
 
108
106
  ### Supported Frameworks
109
107
 
@@ -114,7 +112,8 @@ The instrumentation layer runs inside your dev server process (injected via `--i
114
112
  | Nuxt | Auto-detect |
115
113
  | Vite | Auto-detect |
116
114
  | Astro | Auto-detect |
117
- | Any backend | Via `--command` flag |
115
+ | Express | Auto-detect |
116
+ | Fastify | Auto-detect |
118
117
 
119
118
  ### Supported Databases
120
119
 
@@ -129,16 +128,14 @@ The instrumentation layer runs inside your dev server process (injected via `--i
129
128
 
130
129
  ---
131
130
 
132
- ## CLI Options
131
+ ## Uninstall
133
132
 
134
133
  ```bash
135
- npx brakit dev # Auto-detect and start
136
- npx brakit dev --port 3000 # Custom proxy port (default: 3000)
137
- npx brakit dev --show-static # Show static asset requests
138
- npx brakit dev ./my-app # Specify project directory
139
- npx brakit dev --command "python manage.py" # Any backend, any language
134
+ npx brakit uninstall
140
135
  ```
141
136
 
137
+ Removes the instrumentation file and devDependency. Your app is unchanged.
138
+
142
139
  ---
143
140
 
144
141
  ## Development
@@ -158,25 +155,21 @@ Only 2 production dependencies: `citty` (CLI) and `picocolors` (terminal colors)
158
155
 
159
156
  ### Architecture
160
157
 
161
- For a full walkthrough of how brakit works — the two-process model, adapter
162
- system, analysis engine, and SDK protocol — see
163
- [How Brakit Works](docs/design/architecture.md).
164
-
165
158
  ```
166
159
  src/
160
+ runtime/ In-process entry point, server hooks, capture, safety
167
161
  analysis/ Security scanning, N+1 detection, insights engine
168
162
  rules/ SecurityRule implementations (one file per rule)
169
- cli/ CLI entry point (citty)
163
+ cli/ CLI commands (install, uninstall)
170
164
  dashboard/
171
- api/ REST handlers — requests, flows, telemetry, metrics, ingest
165
+ api/ REST handlers — requests, flows, telemetry, metrics
172
166
  client/ Browser JS generated as template strings
173
167
  views/ Tab renderers (overview, flows, graph, etc.)
174
168
  styles/ CSS modules
175
169
  detect/ Framework auto-detection
176
- instrument/ Node.js --import instrumentation
170
+ instrument/ Runtime hooks and database adapters
177
171
  adapters/ BrakitAdapter implementations (one file per library)
178
- hooks/ Core runtime hooks (fetch, console, errors, context)
179
- proxy/ HTTP reverse proxy, request capture, WebSocket forwarding
172
+ hooks/ Core hooks (fetch, console, errors, context)
180
173
  store/ In-memory telemetry stores + persistent metrics
181
174
  types/ TypeScript definitions by domain
182
175
  ```
@@ -193,7 +186,6 @@ Some areas where help would be great:
193
186
 
194
187
  - **Database adapters** — Drizzle, Mongoose, SQLite, MongoDB
195
188
  - **Security rules** — More patterns, configurable severity
196
- - **Language SDKs** — Python, Go, Ruby (uses the [ingest protocol](docs/design/architecture.md#supporting-other-languages))
197
189
  - **Dashboard** — Request diff, timeline view, HAR export
198
190
 
199
191
  Please open an issue first for larger changes so we can discuss the approach.
package/dist/api.js CHANGED
@@ -1618,7 +1618,7 @@ var AnalysisEngine = class {
1618
1618
  };
1619
1619
 
1620
1620
  // src/index.ts
1621
- var VERSION = "0.7.0";
1621
+ var VERSION = "0.7.2";
1622
1622
  export {
1623
1623
  AdapterRegistry,
1624
1624
  AnalysisEngine,
@@ -693,7 +693,7 @@ import { resolve as resolve2 } from "path";
693
693
  import { randomUUID as randomUUID3 } from "crypto";
694
694
 
695
695
  // src/index.ts
696
- var VERSION = "0.7.0";
696
+ var VERSION = "0.7.2";
697
697
 
698
698
  // src/cli/commands/install.ts
699
699
  var IMPORT_LINE = `import "brakit";`;
@@ -3669,7 +3669,7 @@ var init_src = __esm({
3669
3669
  init_rules();
3670
3670
  init_engine();
3671
3671
  init_insights2();
3672
- VERSION = "0.7.0";
3672
+ VERSION = "0.7.2";
3673
3673
  }
3674
3674
  });
3675
3675
 
@@ -6296,48 +6296,48 @@ function outgoingToIncoming(headers) {
6296
6296
  function captureInProcess(req, res, requestId) {
6297
6297
  const startTime = performance.now();
6298
6298
  const method = req.method ?? "GET";
6299
- const shouldCaptureBody = method !== "GET" && method !== "HEAD";
6300
- const reqChunks = [];
6301
- let reqSize = 0;
6302
- if (shouldCaptureBody) {
6303
- req.on("data", (chunk) => {
6304
- if (reqSize < DEFAULT_MAX_BODY_CAPTURE) {
6305
- reqChunks.push(chunk);
6306
- reqSize += chunk.length;
6307
- }
6308
- });
6309
- }
6310
6299
  const resChunks = [];
6311
6300
  let resSize = 0;
6312
6301
  const originalWrite = res.write;
6313
6302
  const originalEnd = res.end;
6314
- res.write = function(chunk, ...args) {
6315
- if (chunk && resSize < DEFAULT_MAX_BODY_CAPTURE) {
6316
- const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
6317
- resChunks.push(buf);
6318
- resSize += buf.length;
6303
+ res.write = function(...args) {
6304
+ try {
6305
+ const chunk = args[0];
6306
+ if (chunk != null && typeof chunk !== "function" && resSize < DEFAULT_MAX_BODY_CAPTURE) {
6307
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
6308
+ resChunks.push(buf);
6309
+ resSize += buf.length;
6310
+ }
6311
+ } catch {
6319
6312
  }
6320
- return originalWrite.apply(this, [chunk, ...args]);
6313
+ return originalWrite.apply(this, args);
6321
6314
  };
6322
- res.end = function(chunk, ...args) {
6323
- if (chunk && resSize < DEFAULT_MAX_BODY_CAPTURE) {
6324
- const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
6325
- resChunks.push(buf);
6315
+ res.end = function(...args) {
6316
+ try {
6317
+ const chunk = typeof args[0] !== "function" ? args[0] : void 0;
6318
+ if (chunk != null && resSize < DEFAULT_MAX_BODY_CAPTURE) {
6319
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
6320
+ resChunks.push(buf);
6321
+ }
6322
+ } catch {
6323
+ }
6324
+ const result = originalEnd.apply(this, args);
6325
+ try {
6326
+ defaultStore.capture({
6327
+ requestId,
6328
+ method,
6329
+ url: req.url ?? "/",
6330
+ requestHeaders: req.headers,
6331
+ requestBody: null,
6332
+ statusCode: res.statusCode,
6333
+ responseHeaders: outgoingToIncoming(res.getHeaders()),
6334
+ responseBody: resChunks.length > 0 ? Buffer.concat(resChunks) : null,
6335
+ responseContentType: String(res.getHeader("content-type") ?? ""),
6336
+ startTime,
6337
+ config: { maxBodyCapture: DEFAULT_MAX_BODY_CAPTURE }
6338
+ });
6339
+ } catch {
6326
6340
  }
6327
- const result = originalEnd.apply(this, [chunk, ...args]);
6328
- defaultStore.capture({
6329
- requestId,
6330
- method,
6331
- url: req.url ?? "/",
6332
- requestHeaders: req.headers,
6333
- requestBody: reqChunks.length > 0 ? Buffer.concat(reqChunks) : null,
6334
- statusCode: res.statusCode,
6335
- responseHeaders: outgoingToIncoming(res.getHeaders()),
6336
- responseBody: resChunks.length > 0 ? Buffer.concat(resChunks) : null,
6337
- responseContentType: String(res.getHeader("content-type") ?? ""),
6338
- startTime,
6339
- config: { maxBodyCapture: DEFAULT_MAX_BODY_CAPTURE }
6340
- });
6341
6341
  return result;
6342
6342
  };
6343
6343
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brakit",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "See what your API is really doing. Security scanning, N+1 detection, duplicate calls, DB queries — one command, zero config.",
5
5
  "type": "module",
6
6
  "bin": {