@crashsense/react 1.0.0 โ 1.0.1
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 +582 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.shields.io/badge/๐-CrashSense-000000?style=for-the-badge&labelColor=000000" alt="CrashSense" height="60">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">CrashSense</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Error monitoring tells you WHAT crashed.<br>CrashSense tells you WHY โ and how to fix it.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
Intelligent crash diagnosis for JavaScript, React & Vue โ root cause classification, not just stack traces.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://www.npmjs.com/package/@crashsense/core"><img src="https://img.shields.io/npm/v/@crashsense/core?style=flat-square&color=cb0000&label=npm" alt="npm version"></a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/@crashsense/core"><img src="https://img.shields.io/npm/dw/@crashsense/core?style=flat-square&color=cb0000&label=downloads" alt="npm downloads"></a>
|
|
18
|
+
<a href="https://github.com/hoainho/crashsense"><img src="https://img.shields.io/github/stars/hoainho/crashsense?style=flat-square&color=yellow" alt="GitHub stars"></a>
|
|
19
|
+
<a href="https://bundlephobia.com/package/@crashsense/core"><img src="https://img.shields.io/bundlephobia/minzip/@crashsense/core?style=flat-square&color=49a057&label=bundle" alt="bundle size"></a>
|
|
20
|
+
<img src="https://img.shields.io/badge/dependencies-0-49a057?style=flat-square" alt="zero dependencies">
|
|
21
|
+
<img src="https://img.shields.io/badge/TypeScript-first-3178C6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript">
|
|
22
|
+
<a href="https://github.com/hoainho/crashsense/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT license"></a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<br>
|
|
26
|
+
|
|
27
|
+
## The Problem
|
|
28
|
+
|
|
29
|
+
You see this in your error dashboard:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
TypeError: Cannot read properties of undefined (reading 'map')
|
|
33
|
+
at UserList (UserList.tsx:42)
|
|
34
|
+
at renderWithHooks (react-dom.development.js:14985)
|
|
35
|
+
at mountIndeterminateComponent (react-dom.development.js:17811)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Cool. Now what? Is it a race condition? A failed API call? A memory leak? A hydration mismatch? You have no idea. Enjoy your next 3 hours of debugging.
|
|
39
|
+
|
|
40
|
+
## The Solution
|
|
41
|
+
|
|
42
|
+
With CrashSense, the same crash gives you this:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
{
|
|
46
|
+
category: "memory_issue",
|
|
47
|
+
subcategory: "memory_leak",
|
|
48
|
+
confidence: 0.87,
|
|
49
|
+
severity: "critical",
|
|
50
|
+
|
|
51
|
+
contributingFactors: [
|
|
52
|
+
{ factor: "high_memory_utilization", weight: 0.9, evidence: "Heap at 92% (487MB / 528MB)" },
|
|
53
|
+
{ factor: "memory_growing_trend", weight: 0.8, evidence: "Heap growing at 2.3MB/s over 60s" },
|
|
54
|
+
{ factor: "high_long_task_count", weight: 0.6, evidence: "4 long tasks in last 30s (avg 340ms)" },
|
|
55
|
+
],
|
|
56
|
+
|
|
57
|
+
system: {
|
|
58
|
+
memory: { trend: "growing", utilizationPercent: 92.2 },
|
|
59
|
+
cpu: { longTasksLast30s: 4, estimatedBlockingTime: 1360 },
|
|
60
|
+
network: { failedRequestsLast60s: 0, isOnline: true },
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
breadcrumbs: [
|
|
64
|
+
{ type: "navigation", message: "User navigated to /checkout" },
|
|
65
|
+
{ type: "click", message: "User clicked 'Add to Cart'" },
|
|
66
|
+
{ type: "network", message: "POST /api/cart โ 200 (142ms)" },
|
|
67
|
+
{ type: "console", message: "Warning: memory pressure elevated" },
|
|
68
|
+
// ... full trail leading to crash
|
|
69
|
+
],
|
|
70
|
+
|
|
71
|
+
// With @crashsense/ai:
|
|
72
|
+
aiAnalysis: {
|
|
73
|
+
rootCause: "Memory leak in useEffect โ event listener not cleaned up",
|
|
74
|
+
fix: { code: "return () => window.removeEventListener('resize', handler);" },
|
|
75
|
+
prevention: "Always return cleanup functions from useEffect with side effects",
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Root cause identified. Fix suggested. Time saved: 3 hours.**
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Features
|
|
85
|
+
|
|
86
|
+
๐ **7 crash categories** with confidence scoring โ `memory_issue`, `event_loop_blocking`, `framework_react`, `framework_vue`, `network_induced`, `iframe_overload`, `runtime_error`
|
|
87
|
+
|
|
88
|
+
๐ง **AI-powered fix suggestions** โ bring your own LLM (OpenAI, Anthropic, Google, or any compatible endpoint)
|
|
89
|
+
|
|
90
|
+
โก **~7KB gzipped core** โ zero runtime dependencies in all browser packages
|
|
91
|
+
|
|
92
|
+
๐ก๏ธ **Privacy-first** โ emails, IPs, tokens, and credit card numbers auto-scrubbed at the SDK level
|
|
93
|
+
|
|
94
|
+
โ๏ธ **React & Vue adapters** โ hydration mismatch detection, infinite re-render tracking, reactivity loop detection
|
|
95
|
+
|
|
96
|
+
๐จ **Pre-crash warnings** โ 3-tier escalating alerts detect memory pressure *before* the tab dies
|
|
97
|
+
|
|
98
|
+
๐ **Plugin system** โ intercept, enrich, or drop crash events with custom plugins
|
|
99
|
+
|
|
100
|
+
๐ฆ **TypeScript-first** โ full type definitions, tree-shakeable ESM + CJS, SSR-safe
|
|
101
|
+
|
|
102
|
+
๐ **Breadcrumb trail** โ clicks, navigation, network requests, console output, state changes โ automatic
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Install
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm install @crashsense/core
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { createCrashSense } from '@crashsense/core';
|
|
114
|
+
|
|
115
|
+
const cs = createCrashSense({
|
|
116
|
+
appId: 'my-app',
|
|
117
|
+
debug: true,
|
|
118
|
+
onCrash: (report) => {
|
|
119
|
+
console.log(report.event.category); // "memory_issue"
|
|
120
|
+
console.log(report.event.confidence); // 0.87
|
|
121
|
+
console.log(report.event.contributingFactors);
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
That's it. CrashSense is now monitoring memory, event loop, network, and capturing every crash with full system state.
|
|
127
|
+
|
|
128
|
+
<details>
|
|
129
|
+
<summary><strong>โ๏ธ React โ 3 lines to add crash diagnosis</strong></summary>
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm install @crashsense/core @crashsense/react
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { CrashSenseProvider } from '@crashsense/react';
|
|
137
|
+
|
|
138
|
+
function App() {
|
|
139
|
+
return (
|
|
140
|
+
<CrashSenseProvider
|
|
141
|
+
config={{ appId: 'my-app', debug: true }}
|
|
142
|
+
onCrash={(report) => console.log('Crash:', report)}
|
|
143
|
+
>
|
|
144
|
+
<YourApp />
|
|
145
|
+
</CrashSenseProvider>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Automatically captures React-specific crashes: hydration mismatches, infinite re-render loops, hook ordering violations, and lifecycle errors.
|
|
151
|
+
|
|
152
|
+
#### Hooks
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { useCrashSense, useRenderTracker } from '@crashsense/react';
|
|
156
|
+
|
|
157
|
+
function Checkout() {
|
|
158
|
+
const { captureException, addBreadcrumb } = useCrashSense();
|
|
159
|
+
useRenderTracker('Checkout'); // tracks excessive re-renders
|
|
160
|
+
|
|
161
|
+
const handlePay = async () => {
|
|
162
|
+
addBreadcrumb({ type: 'click', message: 'User clicked pay' });
|
|
163
|
+
try {
|
|
164
|
+
await processPayment();
|
|
165
|
+
} catch (err) {
|
|
166
|
+
captureException(err, { action: 'payment' });
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return <button onClick={handlePay}>Pay Now</button>;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
</details>
|
|
175
|
+
|
|
176
|
+
<details>
|
|
177
|
+
<summary><strong>๐ Vue โ plugin + composables</strong></summary>
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npm install @crashsense/core @crashsense/vue
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { createApp } from 'vue';
|
|
185
|
+
import { crashSensePlugin } from '@crashsense/vue';
|
|
186
|
+
|
|
187
|
+
const app = createApp(App);
|
|
188
|
+
app.use(crashSensePlugin, { appId: 'my-app', debug: true });
|
|
189
|
+
app.mount('#app');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Catches Vue-specific crashes: reactivity loops, lifecycle errors, component-level failures via `app.config.errorHandler`.
|
|
193
|
+
|
|
194
|
+
#### Composables
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { useCrashSense, useReactivityTracker } from '@crashsense/vue';
|
|
198
|
+
|
|
199
|
+
const { captureException, addBreadcrumb } = useCrashSense();
|
|
200
|
+
|
|
201
|
+
// Track reactive state for anomaly detection
|
|
202
|
+
useReactivityTracker({
|
|
203
|
+
cartItems: () => store.state.cartItems,
|
|
204
|
+
userProfile: () => store.state.userProfile,
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
</details>
|
|
209
|
+
|
|
210
|
+
<details>
|
|
211
|
+
<summary><strong>๐ง AI Integration โ bring your own LLM</strong></summary>
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
npm install @crashsense/ai
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import { createAIClient } from '@crashsense/ai';
|
|
219
|
+
|
|
220
|
+
const ai = createAIClient({
|
|
221
|
+
endpoint: 'https://api.openai.com/v1/chat/completions',
|
|
222
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
223
|
+
model: 'gpt-4',
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const analysis = await ai.analyze(report.event);
|
|
227
|
+
if (analysis) {
|
|
228
|
+
console.log('Root cause:', analysis.rootCause);
|
|
229
|
+
console.log('Explanation:', analysis.explanation);
|
|
230
|
+
console.log('Fix:', analysis.fix?.code);
|
|
231
|
+
console.log('Prevention:', analysis.prevention);
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Supports OpenAI, Anthropic, Google, or any OpenAI-compatible endpoint. The AI client sends a structured, token-optimized crash payload and returns parsed, validated analysis.
|
|
236
|
+
|
|
237
|
+
</details>
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## CrashSense vs. The Rest
|
|
242
|
+
|
|
243
|
+
| Capability | CrashSense | Sentry | LogRocket | Bugsnag |
|
|
244
|
+
|---|:---:|:---:|:---:|:---:|
|
|
245
|
+
| **Root cause classification** | โ
7 categories + confidence | โ Stack trace only | โ | โ Basic grouping |
|
|
246
|
+
| **Memory leak detection** | โ
Trends + utilization | โ | โ | โ |
|
|
247
|
+
| **Event loop blocking** | โ
Long Task monitoring | โ | โ | โ |
|
|
248
|
+
| **React crash detection** | โ
Hydration, re-renders, hooks | โ ๏ธ ErrorBoundary only | โ ๏ธ Partial | โ ๏ธ Partial |
|
|
249
|
+
| **Vue crash detection** | โ
Reactivity loops, lifecycle | โ ๏ธ Partial | โ ๏ธ Partial | โ ๏ธ Partial |
|
|
250
|
+
| **Pre-crash warnings** | โ
3-tier escalation | โ | โ | โ |
|
|
251
|
+
| **AI fix suggestions** | โ
Bring your own LLM | โ | โ | โ |
|
|
252
|
+
| **PII auto-scrubbing** | โ
SDK-level | โ ๏ธ Server-side | โ | โ ๏ธ Limited |
|
|
253
|
+
| **Bundle size (gzipped)** | **~7KB** | ~30KB | ~80KB | ~15KB |
|
|
254
|
+
| **Runtime dependencies** | **0** | Multiple | Multiple | Multiple |
|
|
255
|
+
| **Open source** | โ
MIT | โ
BSL | โ Proprietary | โ Proprietary |
|
|
256
|
+
| **Pricing** | **Free** | Free tier (5K events) | $99/mo | $59/mo |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Crash Categories
|
|
261
|
+
|
|
262
|
+
| Category | What It Detects | How |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| `runtime_error` | TypeError, ReferenceError, RangeError, etc. | Error type analysis |
|
|
265
|
+
| `memory_issue` | Memory leaks, heap spikes, memory pressure | `performance.memory` + trend analysis |
|
|
266
|
+
| `event_loop_blocking` | Infinite loops, long tasks, frozen UI | Long Task API + frame timing |
|
|
267
|
+
| `framework_react` | Hydration mismatches, infinite re-renders, hook violations | React adapter instrumentation |
|
|
268
|
+
| `framework_vue` | Reactivity loops, lifecycle errors, watcher cascades | Vue adapter instrumentation |
|
|
269
|
+
| `network_induced` | Offline crashes, CORS blocks, timeouts, failed requests | Network monitoring + error analysis |
|
|
270
|
+
| `iframe_overload` | Excessive iframes exhausting memory | MutationObserver + memory correlation |
|
|
271
|
+
|
|
272
|
+
Each crash report includes a **confidence score** (0.0โ1.0) and **contributing factors** with evidence strings, so you know exactly why the classifier made its decision.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Packages
|
|
277
|
+
|
|
278
|
+
| Package | Description | Size |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| [`@crashsense/core`](https://www.npmjs.com/package/@crashsense/core) | Crash detection engine โ monitors, classifiers, event bus | ~7KB |
|
|
281
|
+
| [`@crashsense/react`](https://www.npmjs.com/package/@crashsense/react) | React ErrorBoundary + hooks + hydration detector | ~1.3KB |
|
|
282
|
+
| [`@crashsense/vue`](https://www.npmjs.com/package/@crashsense/vue) | Vue plugin + composables + reactivity tracker | ~1.2KB |
|
|
283
|
+
| [`@crashsense/ai`](https://www.npmjs.com/package/@crashsense/ai) | AI analysis client โ any LLM endpoint | ~3.1KB |
|
|
284
|
+
| [`@crashsense/types`](https://www.npmjs.com/package/@crashsense/types) | Shared TypeScript types | types only |
|
|
285
|
+
| [`@crashsense/utils`](https://www.npmjs.com/package/@crashsense/utils) | Internal utilities | ~2.5KB |
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Configuration
|
|
290
|
+
|
|
291
|
+
| Option | Type | Default | Description |
|
|
292
|
+
|---|---|---|---|
|
|
293
|
+
| `appId` | `string` | *required* | Your application identifier |
|
|
294
|
+
| `environment` | `string` | `'production'` | Environment name |
|
|
295
|
+
| `release` | `string` | `''` | Release/version tag |
|
|
296
|
+
| `sampleRate` | `number` | `1.0` | Event sampling rate (0โ1) |
|
|
297
|
+
| `maxEventsPerMinute` | `number` | `30` | Rate limit for crash events |
|
|
298
|
+
| `enableMemoryMonitoring` | `boolean` | `true` | Monitor memory usage and trends |
|
|
299
|
+
| `enableLongTaskMonitoring` | `boolean` | `true` | Monitor event loop blocking |
|
|
300
|
+
| `enableNetworkMonitoring` | `boolean` | `true` | Monitor network failures |
|
|
301
|
+
| `enableIframeTracking` | `boolean` | `false` | Track iframe additions/removals |
|
|
302
|
+
| `enablePreCrashWarning` | `boolean` | `false` | Enable 3-tier pre-crash warning system |
|
|
303
|
+
| `preCrashMemoryThreshold` | `number` | `0.85` | Memory threshold for critical warnings |
|
|
304
|
+
| `piiScrubbing` | `boolean` | `true` | Auto-scrub emails, IPs, tokens, card numbers |
|
|
305
|
+
| `debug` | `boolean` | `false` | Log crash reports to console |
|
|
306
|
+
| `onCrash` | `(report) => void` | โ | Callback when a crash is detected |
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
<details>
|
|
311
|
+
<summary><strong>๐จ Pre-Crash Warning System</strong></summary>
|
|
312
|
+
|
|
313
|
+
CrashSense detects dangerous system conditions **before** the browser tab crashes:
|
|
314
|
+
|
|
315
|
+
| Level | Memory Trigger | Iframe Trigger | Meaning |
|
|
316
|
+
|---|---|---|---|
|
|
317
|
+
| `elevated` | > 70% heap | > 5 iframes | System under pressure |
|
|
318
|
+
| `critical` | > 85% heap | > 10 iframes | High risk โ take action |
|
|
319
|
+
| `imminent` | > 95% heap | > 15 iframes | Crash likely seconds away |
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
const cs = createCrashSense({
|
|
323
|
+
appId: 'my-app',
|
|
324
|
+
enablePreCrashWarning: true,
|
|
325
|
+
enableIframeTracking: true,
|
|
326
|
+
enableMemoryMonitoring: true,
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Warnings are automatically recorded as breadcrumbs. When a crash occurs, the trail shows the full escalation path.
|
|
331
|
+
|
|
332
|
+
</details>
|
|
333
|
+
|
|
334
|
+
<details>
|
|
335
|
+
<summary><strong>๐ก Iframe Tracking</strong></summary>
|
|
336
|
+
|
|
337
|
+
Uncontrolled iframe loading (ads, widgets, payment forms) can exhaust memory and crash the tab. CrashSense monitors iframe mutations in real-time:
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
const cs = createCrashSense({
|
|
341
|
+
appId: 'my-app',
|
|
342
|
+
enableIframeTracking: true,
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const state = cs.getSystemState();
|
|
346
|
+
console.log('Total iframes:', state.iframe?.totalCount);
|
|
347
|
+
console.log('Cross-origin:', state.iframe?.crossOriginCount);
|
|
348
|
+
console.log('Origins:', state.iframe?.origins);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
</details>
|
|
352
|
+
|
|
353
|
+
<details>
|
|
354
|
+
<summary><strong>๐ Custom Plugins</strong></summary>
|
|
355
|
+
|
|
356
|
+
Plugins intercept, enrich, or drop crash events before they reach your `onCrash` callback:
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
import type { CrashSensePlugin, CrashEvent, CrashSenseCore } from '@crashsense/core';
|
|
360
|
+
|
|
361
|
+
const backendReporter: CrashSensePlugin = {
|
|
362
|
+
name: 'backend-reporter',
|
|
363
|
+
|
|
364
|
+
setup(core: CrashSenseCore) {
|
|
365
|
+
console.log('Reporter initialized for', core.config.appId);
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
teardown() {},
|
|
369
|
+
|
|
370
|
+
onCrashEvent(event: CrashEvent) {
|
|
371
|
+
fetch('/api/crashes', {
|
|
372
|
+
method: 'POST',
|
|
373
|
+
headers: { 'Content-Type': 'application/json' },
|
|
374
|
+
body: JSON.stringify({
|
|
375
|
+
category: event.category,
|
|
376
|
+
subcategory: event.subcategory,
|
|
377
|
+
severity: event.severity,
|
|
378
|
+
message: event.error.message,
|
|
379
|
+
fingerprint: event.fingerprint,
|
|
380
|
+
}),
|
|
381
|
+
}).catch(() => {});
|
|
382
|
+
|
|
383
|
+
return event; // return null to drop the event
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const cs = createCrashSense({ appId: 'my-app' });
|
|
388
|
+
cs.use(backendReporter);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
</details>
|
|
392
|
+
|
|
393
|
+
<details>
|
|
394
|
+
<summary><strong>๐ค Sending Reports to Your Backend</strong></summary>
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
const cs = createCrashSense({
|
|
398
|
+
appId: 'my-app',
|
|
399
|
+
onCrash: async (report) => {
|
|
400
|
+
await fetch('https://your-api.com/crashes', {
|
|
401
|
+
method: 'POST',
|
|
402
|
+
headers: { 'Content-Type': 'application/json' },
|
|
403
|
+
body: JSON.stringify(report),
|
|
404
|
+
});
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Each report includes the full `CrashEvent` with system state, breadcrumbs, device info, contributing factors, and classification. PII is auto-scrubbed before it reaches your callback.
|
|
410
|
+
|
|
411
|
+
</details>
|
|
412
|
+
|
|
413
|
+
<details>
|
|
414
|
+
<summary><strong>๐ Full Example โ React E-Commerce Checkout</strong></summary>
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
import React, { useState, useEffect } from 'react';
|
|
418
|
+
import { CrashSenseProvider, useCrashSense, useRenderTracker } from '@crashsense/react';
|
|
419
|
+
import { createAIClient } from '@crashsense/ai';
|
|
420
|
+
|
|
421
|
+
const aiClient = createAIClient({
|
|
422
|
+
endpoint: 'https://api.openai.com/v1/chat/completions',
|
|
423
|
+
apiKey: process.env.REACT_APP_OPENAI_KEY!,
|
|
424
|
+
model: 'gpt-4',
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
export function App() {
|
|
428
|
+
return (
|
|
429
|
+
<CrashSenseProvider
|
|
430
|
+
config={{
|
|
431
|
+
appId: 'ecommerce-app',
|
|
432
|
+
environment: process.env.NODE_ENV,
|
|
433
|
+
release: '2.3.1',
|
|
434
|
+
enableIframeTracking: true,
|
|
435
|
+
enablePreCrashWarning: true,
|
|
436
|
+
onCrash: async (report) => {
|
|
437
|
+
await fetch('/api/crashes', {
|
|
438
|
+
method: 'POST',
|
|
439
|
+
headers: { 'Content-Type': 'application/json' },
|
|
440
|
+
body: JSON.stringify(report),
|
|
441
|
+
});
|
|
442
|
+
if (report.event.severity === 'critical') {
|
|
443
|
+
const analysis = await aiClient.analyze(report.event);
|
|
444
|
+
console.log('AI fix:', analysis?.fix?.code);
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
}}
|
|
448
|
+
>
|
|
449
|
+
<Checkout />
|
|
450
|
+
</CrashSenseProvider>
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function Checkout() {
|
|
455
|
+
const { captureException, addBreadcrumb, core } = useCrashSense();
|
|
456
|
+
useRenderTracker('Checkout');
|
|
457
|
+
const [cart, setCart] = useState([]);
|
|
458
|
+
|
|
459
|
+
useEffect(() => {
|
|
460
|
+
const user = JSON.parse(localStorage.getItem('user') || '{}');
|
|
461
|
+
if (user.id) core?.setUser({ id: user.id, plan: user.plan });
|
|
462
|
+
}, [core]);
|
|
463
|
+
|
|
464
|
+
async function handleCheckout() {
|
|
465
|
+
addBreadcrumb({ type: 'click', message: 'User clicked checkout' });
|
|
466
|
+
try {
|
|
467
|
+
const res = await fetch('/api/checkout', {
|
|
468
|
+
method: 'POST',
|
|
469
|
+
headers: { 'Content-Type': 'application/json' },
|
|
470
|
+
body: JSON.stringify({ items: cart }),
|
|
471
|
+
});
|
|
472
|
+
if (!res.ok) throw new Error(`Checkout failed: ${res.status}`);
|
|
473
|
+
} catch (error) {
|
|
474
|
+
captureException(error, { action: 'checkout', cartSize: String(cart.length) });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return <button onClick={handleCheckout}>Complete Purchase</button>;
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
See full source: [`examples/react-ecommerce/`](./examples/react-ecommerce/)
|
|
483
|
+
|
|
484
|
+
</details>
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Performance Budget
|
|
489
|
+
|
|
490
|
+
| Metric | Budget |
|
|
491
|
+
|---|---|
|
|
492
|
+
| CPU overhead | < 2% |
|
|
493
|
+
| Memory footprint | < 5MB |
|
|
494
|
+
| Core bundle (gzipped) | < 15KB |
|
|
495
|
+
| SDK errors | **NEVER** crash the host app |
|
|
496
|
+
|
|
497
|
+
All monitoring uses passive browser APIs (`PerformanceObserver`, `MutationObserver`). Zero monkey-patching by default.
|
|
498
|
+
|
|
499
|
+
## Browser Support
|
|
500
|
+
|
|
501
|
+
| Browser | Version |
|
|
502
|
+
|---|---|
|
|
503
|
+
| Chrome | 80+ |
|
|
504
|
+
| Firefox | 80+ |
|
|
505
|
+
| Safari | 14+ |
|
|
506
|
+
| Edge | 80+ |
|
|
507
|
+
| Node.js | 18+ |
|
|
508
|
+
|
|
509
|
+
> `performance.memory` is Chrome-only. Memory monitoring gracefully degrades in other browsers. All other features work cross-browser.
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Development
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
git clone https://github.com/hoainho/crashsense.git
|
|
517
|
+
cd crashsense
|
|
518
|
+
npm install
|
|
519
|
+
npm run build
|
|
520
|
+
npm test
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Monorepo with npm workspaces. Each package builds with [tsup](https://tsup.egoist.dev/) (ESM + CJS + DTS).
|
|
524
|
+
|
|
525
|
+
```
|
|
526
|
+
crashsense/
|
|
527
|
+
packages/
|
|
528
|
+
types/ # Shared TypeScript types
|
|
529
|
+
utils/ # Ring buffer, event bus, fingerprint, PII scrubber
|
|
530
|
+
core/ # Crash detection engine, classifiers, monitors
|
|
531
|
+
react/ # ErrorBoundary, hooks, hydration detector
|
|
532
|
+
vue/ # Plugin, composables, reactivity tracker
|
|
533
|
+
ai/ # LLM client, payload builder, response parser
|
|
534
|
+
examples/
|
|
535
|
+
react-ecommerce/
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Contributing
|
|
541
|
+
|
|
542
|
+
Contributions are welcome. Whether it's a bug report, feature request, or pull request โ all help is appreciated.
|
|
543
|
+
|
|
544
|
+
1. Fork the repo
|
|
545
|
+
2. Create your branch (`git checkout -b feat/amazing-feature`)
|
|
546
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
547
|
+
4. Push to the branch (`git push origin feat/amazing-feature`)
|
|
548
|
+
5. Open a Pull Request
|
|
549
|
+
|
|
550
|
+
See [open issues](https://github.com/hoainho/crashsense/issues) for ideas.
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Changelog
|
|
555
|
+
|
|
556
|
+
### v1.0.0 (2026)
|
|
557
|
+
|
|
558
|
+
- Initial public release
|
|
559
|
+
- 7 crash categories with confidence scoring and contributing factors
|
|
560
|
+
- React and Vue framework adapters
|
|
561
|
+
- AI-powered root cause analysis (OpenAI, Anthropic, Google, custom endpoints)
|
|
562
|
+
- Iframe tracking via MutationObserver
|
|
563
|
+
- Pre-crash warning system with 3-tier escalation
|
|
564
|
+
- Plugin system for extensibility
|
|
565
|
+
- PII scrubbing (emails, IPs, tokens, credit cards)
|
|
566
|
+
- Zero runtime dependencies in all browser packages
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
## License
|
|
571
|
+
|
|
572
|
+
[MIT](./LICENSE) โ Copyright (c) 2026 hoainho
|
|
573
|
+
|
|
574
|
+
## Author
|
|
575
|
+
|
|
576
|
+
**Hoai Nho** โ [GitHub](https://github.com/hoainho) ยท [npm](https://www.npmjs.com/~nhonh) ยท hoainho.work@gmail.com
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
<p align="center">
|
|
581
|
+
<strong>If CrashSense saves you debugging time, <a href="https://github.com/hoainho/crashsense">โญ star the repo</a> โ it helps others find it.</strong>
|
|
582
|
+
</p>
|
package/package.json
CHANGED