@statly/observe 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Statly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # Statly Observe SDK for Node.js
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@statly/observe.svg)](https://www.npmjs.com/package/@statly/observe)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Error tracking and monitoring for JavaScript and TypeScript applications. Capture exceptions, track releases, and debug issues faster.
7
+
8
+ ## Features
9
+
10
+ - Automatic error capturing with stack traces
11
+ - Breadcrumbs for debugging context
12
+ - User context tracking
13
+ - Release tracking
14
+ - Framework integrations (Express, Next.js, Fastify)
15
+ - TypeScript support
16
+ - Minimal overhead
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @statly/observe
22
+ # or
23
+ yarn add @statly/observe
24
+ # or
25
+ pnpm add @statly/observe
26
+ ```
27
+
28
+ ## Getting Your DSN
29
+
30
+ 1. Go to [statly.live/dashboard/observe/setup](https://statly.live/dashboard/observe/setup)
31
+ 2. Create an API key for Observe
32
+ 3. Copy your DSN (format: `https://<api-key>@statly.live/<org-slug>`)
33
+
34
+ ## Quick Start
35
+
36
+ ```typescript
37
+ import { Statly } from '@statly/observe';
38
+
39
+ // Initialize the SDK
40
+ Statly.init({
41
+ dsn: 'https://sk_live_xxx@statly.live/your-org',
42
+ release: '1.0.0',
43
+ environment: 'production',
44
+ });
45
+
46
+ // Errors are captured automatically via global handlers
47
+
48
+ // Manual capture
49
+ try {
50
+ riskyOperation();
51
+ } catch (error) {
52
+ Statly.captureException(error);
53
+ }
54
+
55
+ // Capture a message
56
+ Statly.captureMessage('User completed checkout', 'info');
57
+
58
+ // Set user context
59
+ Statly.setUser({
60
+ id: 'user-123',
61
+ email: 'user@example.com',
62
+ });
63
+
64
+ // Add breadcrumb for debugging
65
+ Statly.addBreadcrumb({
66
+ category: 'auth',
67
+ message: 'User logged in',
68
+ level: 'info',
69
+ });
70
+
71
+ // Flush before exit (important for serverless)
72
+ await Statly.close();
73
+ ```
74
+
75
+ ## Framework Integrations
76
+
77
+ ### Express
78
+
79
+ ```typescript
80
+ import express from 'express';
81
+ import { Statly, requestHandler, expressErrorHandler } from '@statly/observe';
82
+
83
+ const app = express();
84
+
85
+ // Initialize first
86
+ Statly.init({
87
+ dsn: 'https://sk_live_xxx@statly.live/your-org',
88
+ environment: process.env.NODE_ENV,
89
+ });
90
+
91
+ // Add request handler FIRST (before routes)
92
+ app.use(requestHandler());
93
+
94
+ // Your routes
95
+ app.get('/', (req, res) => {
96
+ res.send('Hello World');
97
+ });
98
+
99
+ app.get('/error', (req, res) => {
100
+ throw new Error('Test error');
101
+ });
102
+
103
+ // Add error handler LAST (after routes)
104
+ app.use(expressErrorHandler());
105
+
106
+ app.listen(3000);
107
+ ```
108
+
109
+ ### Next.js (App Router)
110
+
111
+ **Route Handlers:**
112
+
113
+ ```typescript
114
+ // app/api/example/route.ts
115
+ import { withStatly } from '@statly/observe';
116
+
117
+ export const GET = withStatly(async (request) => {
118
+ // Errors are automatically captured
119
+ const data = await fetchData();
120
+ return Response.json({ data });
121
+ });
122
+ ```
123
+
124
+ **Error Boundary:**
125
+
126
+ ```typescript
127
+ // app/error.tsx
128
+ 'use client';
129
+
130
+ import { useEffect } from 'react';
131
+ import { captureNextJsError } from '@statly/observe';
132
+
133
+ export default function Error({
134
+ error,
135
+ reset,
136
+ }: {
137
+ error: Error & { digest?: string };
138
+ reset: () => void;
139
+ }) {
140
+ useEffect(() => {
141
+ captureNextJsError(error);
142
+ }, [error]);
143
+
144
+ return (
145
+ <div>
146
+ <h2>Something went wrong!</h2>
147
+ <button onClick={reset}>Try again</button>
148
+ </div>
149
+ );
150
+ }
151
+ ```
152
+
153
+ **Server Actions:**
154
+
155
+ ```typescript
156
+ 'use server';
157
+
158
+ import { withStatlyServerAction } from '@statly/observe';
159
+
160
+ export const submitForm = withStatlyServerAction(
161
+ async (formData: FormData) => {
162
+ // Your action code - errors are captured automatically
163
+ const email = formData.get('email');
164
+ await saveToDatabase(email);
165
+ },
166
+ 'submitForm' // Action name for grouping
167
+ );
168
+ ```
169
+
170
+ ### Fastify
171
+
172
+ ```typescript
173
+ import Fastify from 'fastify';
174
+ import { Statly, statlyFastifyPlugin } from '@statly/observe';
175
+
176
+ const fastify = Fastify();
177
+
178
+ Statly.init({
179
+ dsn: 'https://sk_live_xxx@statly.live/your-org',
180
+ });
181
+
182
+ // Register the plugin
183
+ fastify.register(statlyFastifyPlugin, {
184
+ captureValidationErrors: true,
185
+ skipStatusCodes: [400, 401, 403, 404], // Don't capture these as errors
186
+ });
187
+
188
+ fastify.get('/', async () => {
189
+ return { hello: 'world' };
190
+ });
191
+
192
+ fastify.listen({ port: 3000 });
193
+ ```
194
+
195
+ ## Configuration Options
196
+
197
+ | Option | Type | Default | Description |
198
+ |--------|------|---------|-------------|
199
+ | `dsn` | `string` | **Required** | Your project's Data Source Name |
200
+ | `environment` | `string` | `undefined` | Environment name (production, staging, development) |
201
+ | `release` | `string` | `undefined` | Release/version identifier for tracking |
202
+ | `debug` | `boolean` | `false` | Enable debug logging to console |
203
+ | `sampleRate` | `number` | `1.0` | Sample rate for events (0.0 to 1.0) |
204
+ | `maxBreadcrumbs` | `number` | `100` | Maximum breadcrumbs to store |
205
+ | `autoCapture` | `boolean` | `true` | Auto-attach global error handlers |
206
+ | `beforeSend` | `function` | `undefined` | Callback to modify/filter events before sending |
207
+
208
+ ### beforeSend Example
209
+
210
+ ```typescript
211
+ Statly.init({
212
+ dsn: '...',
213
+ beforeSend: (event) => {
214
+ // Filter out specific errors
215
+ if (event.message?.includes('ResizeObserver')) {
216
+ return null; // Drop the event
217
+ }
218
+
219
+ // Scrub sensitive data
220
+ if (event.extra?.password) {
221
+ delete event.extra.password;
222
+ }
223
+
224
+ return event;
225
+ },
226
+ });
227
+ ```
228
+
229
+ ## API Reference
230
+
231
+ ### Statly.captureException(error, context?)
232
+
233
+ Capture an exception with optional additional context:
234
+
235
+ ```typescript
236
+ try {
237
+ await processPayment(order);
238
+ } catch (error) {
239
+ Statly.captureException(error, {
240
+ extra: {
241
+ orderId: order.id,
242
+ amount: order.total,
243
+ },
244
+ tags: {
245
+ paymentProvider: 'stripe',
246
+ },
247
+ });
248
+ }
249
+ ```
250
+
251
+ ### Statly.captureMessage(message, level?)
252
+
253
+ Capture a message event:
254
+
255
+ ```typescript
256
+ Statly.captureMessage('User signed up', 'info');
257
+ Statly.captureMessage('Payment failed after 3 retries', 'warning');
258
+ Statly.captureMessage('Database connection lost', 'error');
259
+ ```
260
+
261
+ Levels: `'debug'` | `'info'` | `'warning'` | `'error'` | `'fatal'`
262
+
263
+ ### Statly.setUser(user)
264
+
265
+ Set user context for all subsequent events:
266
+
267
+ ```typescript
268
+ Statly.setUser({
269
+ id: 'user-123',
270
+ email: 'user@example.com',
271
+ username: 'johndoe',
272
+ // Custom fields
273
+ subscription: 'premium',
274
+ });
275
+
276
+ // Clear user on logout
277
+ Statly.setUser(null);
278
+ ```
279
+
280
+ ### Statly.setTag(key, value) / Statly.setTags(tags)
281
+
282
+ Set tags for filtering and searching:
283
+
284
+ ```typescript
285
+ Statly.setTag('version', '1.0.0');
286
+
287
+ Statly.setTags({
288
+ environment: 'production',
289
+ server: 'web-1',
290
+ region: 'us-east-1',
291
+ });
292
+ ```
293
+
294
+ ### Statly.addBreadcrumb(breadcrumb)
295
+
296
+ Add a breadcrumb for debugging context:
297
+
298
+ ```typescript
299
+ Statly.addBreadcrumb({
300
+ message: 'User clicked checkout button',
301
+ category: 'ui.click',
302
+ level: 'info',
303
+ data: {
304
+ buttonId: 'checkout-btn',
305
+ cartItems: 3,
306
+ },
307
+ });
308
+ ```
309
+
310
+ ### Statly.flush() / Statly.close()
311
+
312
+ ```typescript
313
+ // Flush pending events (keeps SDK running)
314
+ await Statly.flush();
315
+
316
+ // Flush and close (use before process exit)
317
+ await Statly.close();
318
+ ```
319
+
320
+ ## TypeScript Support
321
+
322
+ Full TypeScript support with exported types:
323
+
324
+ ```typescript
325
+ import type {
326
+ StatlyOptions,
327
+ StatlyEvent,
328
+ User,
329
+ Breadcrumb,
330
+ EventLevel,
331
+ } from '@statly/observe';
332
+ ```
333
+
334
+ ## Requirements
335
+
336
+ - Node.js 16+
337
+ - Works in browser environments (with bundler)
338
+
339
+ ## License
340
+
341
+ MIT