blinker-sdk 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 CHANGED
@@ -7,6 +7,7 @@ Universal JavaScript SDK for error tracking and event capture. Works with **any
7
7
  - 🚀 **Zero dependencies** - Lightweight and fast
8
8
  - 🌐 **Universal** - Works in any JavaScript environment
9
9
  - 🔄 **Automatic error capture** - Catches global errors and unhandled rejections
10
+ - 🧠 **Smart filtering** - Ignores common non-bugs (401, 403, ResizeObserver) by default
10
11
  - 📊 **Custom events** - Track any event you need
11
12
  - 📦 **Multiple formats** - ESM, CommonJS, and UMD (CDN)
12
13
  - 🔒 **Type-safe** - Full TypeScript support
@@ -29,7 +30,7 @@ pnpm add blinker-sdk
29
30
  <script src="https://unpkg.com/blinker-sdk/dist/blinker.min.js"></script>
30
31
  <script>
31
32
  const { blinker } = BlinkerSDK;
32
- blinker.init({ token: 'your-token', api: 'https://api.example.com' });
33
+ blinker.init({ token: 'your-token' });
33
34
  </script>
34
35
  ```
35
36
 
@@ -38,13 +39,12 @@ pnpm add blinker-sdk
38
39
  ```javascript
39
40
  import { blinker } from 'blinker-sdk';
40
41
 
41
- // Initialize the SDK
42
- blinker.init({
43
- token: 'your-blinker-token',
44
- api: 'https://api.example.com'
45
- });
42
+ // Initialize the SDK - just pass your token!
43
+ blinker.init({ token: 'your-blinker-token' });
46
44
 
47
45
  // That's it! Errors are now automatically captured.
46
+ // ✅ Ignores 401/403 errors by default
47
+ // ✅ Filters out common browser noise (ResizeObserver, Script error)
48
48
  ```
49
49
 
50
50
  ## Usage
@@ -54,15 +54,126 @@ blinker.init({
54
54
  ```javascript
55
55
  import { blinker } from 'blinker-sdk';
56
56
 
57
+ // Minimal setup - just the token!
58
+ blinker.init({ token: 'your-blinker-token' });
59
+
60
+ // Or with custom options
57
61
  blinker.init({
58
62
  token: 'your-blinker-token', // Required: Your API token
59
- api: 'https://api.example.com', // Required: API endpoint
60
63
  captureErrors: true, // Optional: Auto-capture errors (default: true)
61
64
  captureRejections: true, // Optional: Auto-capture promise rejections (default: true)
62
65
  debug: false // Optional: Enable debug logging (default: false)
63
66
  });
64
67
  ```
65
68
 
69
+ ### Error Filters (Smart Defaults)
70
+
71
+ The SDK comes with **intelligent default filters** that ignore common non-bug errors. This prevents your error tracking from being cluttered with expected behaviors like authentication failures.
72
+
73
+ #### Default Behavior
74
+
75
+ By default, the SDK **ignores**:
76
+ - `401` and `403` HTTP errors (authentication/authorization - usually expected behavior)
77
+ - `ResizeObserver loop` errors (benign browser behavior)
78
+ - `Script error` (cross-origin errors with no useful info)
79
+
80
+ ```javascript
81
+ // Minimal initialization - all defaults applied automatically!
82
+ blinker.init({ token: 'your-token' });
83
+ // ✅ Automatically ignores: 401, 403, ResizeObserver loop, Script error
84
+ ```
85
+
86
+ #### Capture Everything
87
+
88
+ If you want to capture ALL errors including auth failures:
89
+
90
+ ```javascript
91
+ blinker.init({
92
+ token: 'your-token',
93
+ filters: { captureAll: true }
94
+ });
95
+ ```
96
+
97
+ #### Custom HTTP Code Filters
98
+
99
+ Customize which HTTP codes to ignore:
100
+
101
+ ```javascript
102
+ // Only ignore 401 (capture 403)
103
+ blinker.init({
104
+ token: 'your-token',
105
+ filters: { ignoreHttpCodes: [401] }
106
+ });
107
+
108
+ // Ignore more codes
109
+ blinker.init({
110
+ token: 'your-token',
111
+ filters: { ignoreHttpCodes: [401, 403, 404, 429] }
112
+ });
113
+
114
+ // Capture ALL HTTP errors (empty array)
115
+ blinker.init({
116
+ token: 'your-token',
117
+ filters: { ignoreHttpCodes: [] }
118
+ });
119
+ ```
120
+
121
+ #### Ignore Specific Error Types
122
+
123
+ Filter out specific JavaScript error types:
124
+
125
+ ```javascript
126
+ blinker.init({
127
+ token: 'your-token',
128
+ filters: { ignoreErrorTypes: ['TypeError', 'SyntaxError'] }
129
+ });
130
+ ```
131
+
132
+ #### Ignore Message Patterns
133
+
134
+ Filter errors by message content (case-insensitive substring matching):
135
+
136
+ ```javascript
137
+ blinker.init({
138
+ token: 'your-token',
139
+ filters: {
140
+ ignoreMessagePatterns: [
141
+ 'ResizeObserver loop', // Default
142
+ 'Script error', // Default
143
+ 'ChunkLoadError', // Webpack chunk loading
144
+ 'Loading chunk', // Next.js chunk loading
145
+ 'Network request failed', // Offline users
146
+ 'AbortError' // Cancelled requests
147
+ ]
148
+ }
149
+ });
150
+ ```
151
+
152
+ #### Full Filter Configuration
153
+
154
+ All filter options together:
155
+
156
+ ```javascript
157
+ blinker.init({
158
+ token: 'your-token',
159
+ filters: {
160
+ ignoreHttpCodes: [401, 403, 404],
161
+ ignoreErrorTypes: ['AbortError'],
162
+ ignoreMessagePatterns: ['ResizeObserver loop', 'Script error', 'ChunkLoadError'],
163
+ captureAll: false
164
+ }
165
+ });
166
+ ```
167
+
168
+ #### Check Current Filters
169
+
170
+ ```javascript
171
+ // Get the current filter configuration
172
+ const filters = blinker.getFilters();
173
+ console.log(filters);
174
+ // { ignoreHttpCodes: [401, 403], ignoreErrorTypes: [], ... }
175
+ ```
176
+
66
177
  ### Track Custom Events
67
178
 
68
179
  ```javascript
@@ -123,10 +234,7 @@ blinker.destroy();
123
234
  // app.jsx or index.jsx
124
235
  import { blinker } from 'blinker-sdk';
125
236
 
126
- blinker.init({
127
- token: process.env.REACT_APP_BLINKER_TOKEN,
128
- api: process.env.REACT_APP_BLINKER_API
129
- });
237
+ blinker.init({ token: process.env.REACT_APP_BLINKER_TOKEN });
130
238
 
131
239
  function App() {
132
240
  const handleClick = () => {
@@ -148,10 +256,7 @@ import { blinker } from 'blinker-sdk';
148
256
 
149
257
  export default function RootLayout({ children }) {
150
258
  useEffect(() => {
151
- blinker.init({
152
- token: process.env.NEXT_PUBLIC_BLINKER_TOKEN,
153
- api: process.env.NEXT_PUBLIC_BLINKER_API
154
- });
259
+ blinker.init({ token: process.env.NEXT_PUBLIC_BLINKER_TOKEN });
155
260
  }, []);
156
261
 
157
262
  return (
@@ -170,10 +275,7 @@ import { createApp } from 'vue';
170
275
  import { blinker } from 'blinker-sdk';
171
276
  import App from './App.vue';
172
277
 
173
- blinker.init({
174
- token: import.meta.env.VITE_BLINKER_TOKEN,
175
- api: import.meta.env.VITE_BLINKER_API
176
- });
278
+ blinker.init({ token: import.meta.env.VITE_BLINKER_TOKEN });
177
279
 
178
280
  createApp(App).mount('#app');
179
281
  ```
@@ -184,10 +286,7 @@ createApp(App).mount('#app');
184
286
  // app.module.ts
185
287
  import { blinker } from 'blinker-sdk';
186
288
 
187
- blinker.init({
188
- token: environment.blinkerToken,
189
- api: environment.blinkerApi
190
- });
289
+ blinker.init({ token: environment.blinkerToken });
191
290
 
192
291
  @NgModule({
193
292
  // ...
@@ -209,10 +308,7 @@ export class AppModule {}
209
308
  <script>
210
309
  const { blinker } = BlinkerSDK;
211
310
 
212
- blinker.init({
213
- token: 'your-token',
214
- api: 'https://api.example.com'
215
- });
311
+ blinker.init({ token: 'your-token' });
216
312
 
217
313
  document.getElementById('myButton').addEventListener('click', () => {
218
314
  blinker.track('click', 'Button clicked');
@@ -231,10 +327,19 @@ Initialize the SDK with configuration options.
231
327
  | Option | Type | Default | Description |
232
328
  |--------|------|---------|-------------|
233
329
  | `token` | `string` | **required** | Your Blinker API token |
234
- | `api` | `string` | **required** | API endpoint URL |
235
330
  | `captureErrors` | `boolean` | `true` | Auto-capture window errors |
236
331
  | `captureRejections` | `boolean` | `true` | Auto-capture unhandled rejections |
237
332
  | `debug` | `boolean` | `false` | Enable debug logging |
333
+ | `filters` | `FilterSettings` | see below | Error filter configuration |
334
+
335
+ #### FilterSettings
336
+
337
+ | Option | Type | Default | Description |
338
+ |--------|------|---------|-------------|
339
+ | `ignoreHttpCodes` | `number[]` | `[401, 403]` | HTTP status codes to ignore |
340
+ | `ignoreErrorTypes` | `string[]` | `[]` | JS error types to ignore (e.g., 'TypeError') |
341
+ | `ignoreMessagePatterns` | `string[]` | `['ResizeObserver loop', 'Script error']` | Message patterns to ignore |
342
+ | `captureAll` | `boolean` | `false` | When true, disables all filters |
238
343
 
239
344
  ### `blinker.track(type, message, payload?)`
240
345
 
@@ -274,6 +379,15 @@ Check if SDK is initialized. Returns `boolean`.
274
379
 
275
380
  Get current configuration (without token). Returns config object or `null`.
276
381
 
382
+ ### `blinker.getFilters()`
383
+
384
+ Get current filter settings. Returns `FilterSettings` object.
385
+
386
+ ```javascript
387
+ const filters = blinker.getFilters();
388
+ // { ignoreHttpCodes: [401, 403], ignoreErrorTypes: [], ignoreMessagePatterns: [...], captureAll: false }
389
+ ```
390
+
277
391
  ### `blinker.destroy()`
278
392
 
279
393
  Remove error handlers and reset SDK state.
@@ -300,28 +414,38 @@ Events sent to the API have the following structure:
300
414
  The SDK is written in TypeScript and includes type definitions.
301
415
 
302
416
  ```typescript
303
- import { blinker, BlinkerConfig, BlinkerEvent } from 'blinker-sdk';
417
+ import { blinker, BlinkerConfig, FilterSettings } from 'blinker-sdk';
304
418
 
419
+ // Minimal config - just the token!
420
+ blinker.init({ token: 'your-token' });
421
+
422
+ // Or with full typed config
305
423
  const config: BlinkerConfig = {
306
424
  token: 'your-token',
307
- api: 'https://api.example.com'
425
+ filters: {
426
+ ignoreHttpCodes: [401, 403, 404],
427
+ captureAll: false
428
+ }
308
429
  };
309
430
 
310
431
  blinker.init(config);
432
+
433
+ // Get typed filters
434
+ const filters: FilterSettings = blinker.getFilters();
311
435
  ```
312
436
 
313
437
  ## Multiple Instances
314
438
 
315
- If you need multiple SDK instances:
439
+ If you need multiple SDK instances (e.g., different tokens for different app sections):
316
440
 
317
441
  ```javascript
318
442
  import { Blinker } from 'blinker-sdk';
319
443
 
320
- const instance1 = new Blinker();
321
- const instance2 = new Blinker();
444
+ const frontendErrors = new Blinker();
445
+ const backendErrors = new Blinker();
322
446
 
323
- instance1.init({ token: 'token1', api: 'https://api1.example.com' });
324
- instance2.init({ token: 'token2', api: 'https://api2.example.com' });
447
+ frontendErrors.init({ token: 'frontend-token' });
448
+ backendErrors.init({ token: 'backend-token' });
325
449
  ```
326
450
 
327
451
  ## Browser Support
package/dist/Blinker.d.ts CHANGED
@@ -2,15 +2,29 @@
2
2
  * Blinker SDK Main Class
3
3
  * Universal JavaScript SDK for error tracking and event capture
4
4
  */
5
- import type { BlinkerConfig, SendResult } from './types';
5
+ import type { BlinkerConfig, SendResult, FilterSettings } from './types';
6
+ /**
7
+ * Default filter settings
8
+ * These are sensible defaults that ignore common non-bug errors
9
+ */
10
+ export declare const DEFAULT_FILTERS: Required<FilterSettings>;
6
11
  export declare class Blinker {
7
12
  private config;
8
13
  private initialized;
14
+ private filters;
9
15
  /**
10
16
  * Initialize the Blinker SDK
11
17
  * @param config Configuration options
12
18
  */
13
19
  init(config: BlinkerConfig): void;
20
+ /**
21
+ * Check if an error should be captured based on filter settings
22
+ * @param message Error message
23
+ * @param errorType Optional JS error type (e.g., 'TypeError')
24
+ * @param httpCode Optional HTTP status code
25
+ * @returns true if the error should be captured, false if filtered out
26
+ */
27
+ private shouldCapture;
14
28
  /**
15
29
  * Track a custom event
16
30
  * @param type Event type (e.g., 'click', 'pageview', 'custom')
@@ -21,7 +35,7 @@ export declare class Blinker {
21
35
  /**
22
36
  * Track an error manually
23
37
  * @param error Error object or message
24
- * @param additionalPayload Optional additional data
38
+ * @param additionalPayload Optional additional data (can include httpCode for filtering)
25
39
  */
26
40
  captureError(error: Error | string, additionalPayload?: Record<string, unknown>): Promise<SendResult>;
27
41
  /**
@@ -43,5 +57,9 @@ export declare class Blinker {
43
57
  * Removes error handlers and resets state
44
58
  */
45
59
  destroy(): void;
60
+ /**
61
+ * Get current filter settings
62
+ */
63
+ getFilters(): FilterSettings;
46
64
  }
47
65
  //# sourceMappingURL=Blinker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Blinker.d.ts","sourceRoot":"","sources":["../src/Blinker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAwB,UAAU,EAAE,MAAM,SAAS,CAAC;AAI/E,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,WAAW,CAAkB;IAErC;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IA6CjC;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAoB5F;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAcrG;;;;OAIG;IACH,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IASlG;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,IAAI;IAOhD;;;OAGG;IACH,OAAO,IAAI,IAAI;CAWhB"}
1
+ {"version":3,"file":"Blinker.d.ts","sourceRoot":"","sources":["../src/Blinker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAwB,UAAU,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAU/F;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,cAAc,CAapD,CAAC;AAEF,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,OAAO,CAAoD;IAEnE;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IA2DjC;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAwCrB;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAoB5F;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAyBrG;;;;OAIG;IACH,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IASlG;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,IAAI;IAOhD;;;OAGG;IACH,OAAO,IAAI,IAAI;IAaf;;OAEG;IACH,UAAU,IAAI,cAAc;CAG7B"}
@@ -1 +1 @@
1
- "use strict";var BlinkerSDK=(()=>{var w=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var b=(s,e)=>{for(var n in e)w(s,n,{get:e[n],enumerable:!0})},S=(s,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of B(e))!R.call(s,r)&&r!==n&&w(s,r,{get:()=>e[r],enumerable:!(t=v(e,r))||t.enumerable});return s};var P=s=>S(w({},"__esModule",{value:!0}),s);var O={};b(O,{Blinker:()=>f,blinker:()=>h,default:()=>j});async function y(s,e,n,t=!1){let r=`${s.replace(/\/$/,"")}/events`,l=async()=>{try{let o=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json","x-blinker-token":e},body:JSON.stringify({type:n.type,message:n.message,payload:n.payload||{},timestamp:n.timestamp,url:n.url,userAgent:n.userAgent})});if(!o.ok){let i=await o.text().catch(()=>"Unknown error");return t&&console.error(`[Blinker] Failed to send event: ${o.status} - ${i}`),{success:!1,error:`HTTP ${o.status}: ${i}`}}return t&&console.log("[Blinker] Event sent successfully:",n.type),{success:!0}}catch(o){let i=o instanceof Error?o.message:"Unknown error";return t&&console.error("[Blinker] Error sending event:",i),{success:!1,error:i}}},a=await l();return!a.success&&typeof navigator!="undefined"&&!navigator.onLine&&(t&&console.log("[Blinker] Offline, waiting for connection to retry..."),await new Promise(d=>{let p=setTimeout(()=>d(!1),3e4),g=()=>{clearTimeout(p),typeof window!="undefined"&&window.removeEventListener("online",g),d(!0)};typeof window!="undefined"?window.addEventListener("online",g):d(!1)}))?(t&&console.log("[Blinker] Back online, retrying..."),l()):a}var c=null,u=null,k=!1;function m(s,e={}){let{captureErrors:n=!0,captureRejections:t=!0,debug:r=!1}=e;if(k){r&&console.warn("[Blinker] Error handlers already set up");return}if(typeof window=="undefined"){r&&console.log("[Blinker] Not in browser environment, skipping error handlers");return}n&&(c=window.onerror,window.onerror=function(l,a,o,i,d){let p=typeof l=="string"?l:l.type||"Unknown error",g={source:a,lineno:o,colno:i,stack:d==null?void 0:d.stack,errorType:d==null?void 0:d.name};return r&&console.log("[Blinker] Captured error:",p),s("error",p,g),typeof c=="function"?c.call(window,l,a,o,i,d):!1}),t&&(u=window.onunhandledrejection,window.onunhandledrejection=function(l){let a="Unhandled Rejection",o={},i=l.reason;if(i instanceof Error)a=i.message||a,o.stack=i.stack,o.errorType=i.name;else if(typeof i=="string")a=i;else if(i!=null)try{a=JSON.stringify(i)}catch(d){a=String(i)}r&&console.log("[Blinker] Captured unhandled rejection:",a),s("error",a,o),typeof u=="function"&&u.call(window,l)}),k=!0}function E(){typeof window!="undefined"&&(c!==void 0&&(window.onerror=c),u!==void 0&&(window.onunhandledrejection=u),c=null,u=null,k=!1)}var f=class{constructor(){this.config=null;this.initialized=!1}init(e){if(this.initialized){e.debug&&console.warn("[Blinker] SDK already initialized");return}if(!e.token)throw new Error("[Blinker] Token is required");if(!e.api)throw new Error("[Blinker] API endpoint is required");this.config={captureErrors:!0,captureRejections:!0,debug:!1,...e},(this.config.captureErrors||this.config.captureRejections)&&m((n,t,r)=>{this.track(n,t,r)},{captureErrors:this.config.captureErrors,captureRejections:this.config.captureRejections,debug:this.config.debug}),this.initialized=!0,this.config.debug&&console.log("[Blinker] SDK initialized successfully")}track(e,n,t){var l;if(!this.initialized||!this.config)return(l=this.config)!=null&&l.debug&&console.warn("[Blinker] SDK not initialized. Call blinker.init() first."),Promise.resolve({success:!1,error:"SDK not initialized"});let r={type:e,message:n,payload:t,timestamp:new Date().toISOString(),url:typeof window!="undefined"?window.location.href:void 0,userAgent:typeof navigator!="undefined"?navigator.userAgent:void 0};return y(this.config.api,this.config.token,r,this.config.debug)}captureError(e,n){let t=e instanceof Error?e.message:e,r={...n};return e instanceof Error&&(r.stack=e.stack,r.errorType=e.name),this.track("error",t,r)}trackPageView(e,n){let t=e||(typeof window!="undefined"?window.location.pathname:"unknown");return this.track("pageview",t,{...n,referrer:typeof document!="undefined"?document.referrer:void 0})}isInitialized(){return this.initialized}getConfig(){if(!this.config)return null;let{token:e,...n}=this.config;return n}destroy(){var n;let e=(n=this.config)==null?void 0:n.debug;E(),this.config=null,this.initialized=!1,e&&console.log("[Blinker] SDK destroyed")}};var h=new f;var j=h;return P(O);})();
1
+ "use strict";var BlinkerSDK=(()=>{var h=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var T=(u,e)=>{for(var n in e)h(u,n,{get:e[n],enumerable:!0})},P=(u,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of S(e))!C.call(u,t)&&t!==n&&h(u,t,{get:()=>e[t],enumerable:!(r=R(e,t))||r.enumerable});return u};var j=u=>P(h({},"__esModule",{value:!0}),u);var F={};T(F,{Blinker:()=>k,DEFAULT_FILTERS:()=>c,blinker:()=>b,default:()=>x});async function m(u,e,n,r=!1){let t=`${u.replace(/\/$/,"")}/events`,i=async()=>{try{let s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","x-blinker-token":e},body:JSON.stringify({type:n.type,message:n.message,payload:n.payload||{},timestamp:n.timestamp,url:n.url,userAgent:n.userAgent})});if(!s.ok){let o=await s.text().catch(()=>"Unknown error");return r&&console.error(`[Blinker] Failed to send event: ${s.status} - ${o}`),{success:!1,error:`HTTP ${s.status}: ${o}`}}return r&&console.log("[Blinker] Event sent successfully:",n.type),{success:!0}}catch(s){let o=s instanceof Error?s.message:"Unknown error";return r&&console.error("[Blinker] Error sending event:",o),{success:!1,error:o}}},l=await i();return!l.success&&typeof navigator!="undefined"&&!navigator.onLine&&(r&&console.log("[Blinker] Offline, waiting for connection to retry..."),await new Promise(a=>{let d=setTimeout(()=>a(!1),3e4),f=()=>{clearTimeout(d),typeof window!="undefined"&&window.removeEventListener("online",f),a(!0)};typeof window!="undefined"?window.addEventListener("online",f):a(!1)}))?(r&&console.log("[Blinker] Back online, retrying..."),i()):l}var g=null,p=null,E=!1;function v(u,e={}){let{captureErrors:n=!0,captureRejections:r=!0,debug:t=!1}=e;if(E){t&&console.warn("[Blinker] Error handlers already set up");return}if(typeof window=="undefined"){t&&console.log("[Blinker] Not in browser environment, skipping error handlers");return}n&&(g=window.onerror,window.onerror=function(i,l,s,o,a){let d=typeof i=="string"?i:i.type||"Unknown error",f={source:l,lineno:s,colno:o,stack:a==null?void 0:a.stack,errorType:a==null?void 0:a.name};return t&&console.log("[Blinker] Captured error:",d),u("error",d,f),typeof g=="function"?g.call(window,i,l,s,o,a):!1}),r&&(p=window.onunhandledrejection,window.onunhandledrejection=function(i){let l="Unhandled Rejection",s={},o=i.reason;if(o instanceof Error)l=o.message||l,s.stack=o.stack,s.errorType=o.name;else if(typeof o=="string")l=o;else if(o!=null)try{l=JSON.stringify(o)}catch(a){l=String(o)}t&&console.log("[Blinker] Captured unhandled rejection:",l),u("error",l,s),typeof p=="function"&&p.call(window,i)}),E=!0}function B(){typeof window!="undefined"&&(g!==void 0&&(window.onerror=g),p!==void 0&&(window.onunhandledrejection=p),g=null,p=null,E=!1)}var O="https://api.blinker.live",c={ignoreHttpCodes:[401,403],ignoreErrorTypes:[],ignoreMessagePatterns:["ResizeObserver loop","Script error","ResizeObserver loop completed"],captureAll:!1},k=class{constructor(){this.config=null;this.initialized=!1;this.filters={...c}}init(e){var n,r,t,i,l,s,o,a;if(this.initialized){e.debug&&console.warn("[Blinker] SDK already initialized");return}if(!e.token)throw new Error("[Blinker] Token is required");this.config={captureErrors:!0,captureRejections:!0,debug:!1,...e},this.filters={ignoreHttpCodes:(r=(n=e.filters)==null?void 0:n.ignoreHttpCodes)!=null?r:c.ignoreHttpCodes,ignoreErrorTypes:(i=(t=e.filters)==null?void 0:t.ignoreErrorTypes)!=null?i:c.ignoreErrorTypes,ignoreMessagePatterns:(s=(l=e.filters)==null?void 0:l.ignoreMessagePatterns)!=null?s:c.ignoreMessagePatterns,captureAll:(a=(o=e.filters)==null?void 0:o.captureAll)!=null?a:c.captureAll},this.config.debug&&console.log("[Blinker] Filters configured:",this.filters),(this.config.captureErrors||this.config.captureRejections)&&v((d,f,w)=>{var y;this.shouldCapture(f,w==null?void 0:w.errorType)?this.track(d,f,w):(y=this.config)!=null&&y.debug&&console.log("[Blinker] Error filtered out:",f)},{captureErrors:this.config.captureErrors,captureRejections:this.config.captureRejections,debug:this.config.debug}),this.initialized=!0,this.config.debug&&console.log("[Blinker] SDK initialized successfully")}shouldCapture(e,n,r){if(this.filters.captureAll)return!0;if(r!==void 0&&this.filters.ignoreHttpCodes.includes(r)||n&&this.filters.ignoreErrorTypes.includes(n))return!1;for(let t of this.filters.ignoreMessagePatterns)if(e.toLowerCase().includes(t.toLowerCase()))return!1;if(r===void 0){let t=e.match(/(?:HTTP\s*|status[:\s]*)?(\d{3})(?:\s|$|:)/i);if(t){let i=parseInt(t[1],10);if(i>=100&&i<600&&this.filters.ignoreHttpCodes.includes(i))return!1}}return!0}track(e,n,r){var i;if(!this.initialized||!this.config)return(i=this.config)!=null&&i.debug&&console.warn("[Blinker] SDK not initialized. Call blinker.init() first."),Promise.resolve({success:!1,error:"SDK not initialized"});let t={type:e,message:n,payload:r,timestamp:new Date().toISOString(),url:typeof window!="undefined"?window.location.href:void 0,userAgent:typeof navigator!="undefined"?navigator.userAgent:void 0};return m(O,this.config.token,t,this.config.debug)}captureError(e,n){var s;let r=e instanceof Error?e.message:e,t=e instanceof Error?e.name:void 0,i=n==null?void 0:n.httpCode;if(!this.shouldCapture(r,t,i))return(s=this.config)!=null&&s.debug&&console.log("[Blinker] Error filtered out:",{message:r,errorType:t,httpCode:i}),Promise.resolve({success:!0,error:"Filtered out by settings"});let l={...n};return e instanceof Error&&(l.stack=e.stack,l.errorType=e.name),this.track("error",r,l)}trackPageView(e,n){let r=e||(typeof window!="undefined"?window.location.pathname:"unknown");return this.track("pageview",r,{...n,referrer:typeof document!="undefined"?document.referrer:void 0})}isInitialized(){return this.initialized}getConfig(){if(!this.config)return null;let{token:e,...n}=this.config;return n}destroy(){var n;let e=(n=this.config)==null?void 0:n.debug;B(),this.config=null,this.initialized=!1,this.filters={...c},e&&console.log("[Blinker] SDK destroyed")}getFilters(){return{...this.filters}}};var b=new k;var x=b;return j(F);})();
package/dist/index.cjs.js CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  Blinker: () => Blinker,
24
+ DEFAULT_FILTERS: () => DEFAULT_FILTERS,
24
25
  blinker: () => blinker,
25
26
  default: () => index_default
26
27
  });
@@ -181,16 +182,36 @@ function teardownErrorHandlers() {
181
182
  }
182
183
 
183
184
  // src/Blinker.ts
185
+ var BLINKER_API = "https://api.blinker.live";
186
+ var DEFAULT_FILTERS = {
187
+ // Auth/permission errors are usually expected behavior, not bugs
188
+ ignoreHttpCodes: [401, 403],
189
+ // All JS error types are captured by default
190
+ ignoreErrorTypes: [],
191
+ // Common benign browser errors that aren't actionable
192
+ ignoreMessagePatterns: [
193
+ "ResizeObserver loop",
194
+ // Common benign browser error
195
+ "Script error",
196
+ // Cross-origin script errors (no useful info)
197
+ "ResizeObserver loop completed"
198
+ // Another variant of ResizeObserver
199
+ ],
200
+ // By default, respect the filters
201
+ captureAll: false
202
+ };
184
203
  var Blinker = class {
185
204
  constructor() {
186
205
  this.config = null;
187
206
  this.initialized = false;
207
+ this.filters = { ...DEFAULT_FILTERS };
188
208
  }
189
209
  /**
190
210
  * Initialize the Blinker SDK
191
211
  * @param config Configuration options
192
212
  */
193
213
  init(config) {
214
+ var _a, _b, _c, _d, _e, _f, _g, _h;
194
215
  if (this.initialized) {
195
216
  if (config.debug) {
196
217
  console.warn("[Blinker] SDK already initialized");
@@ -200,19 +221,30 @@ var Blinker = class {
200
221
  if (!config.token) {
201
222
  throw new Error("[Blinker] Token is required");
202
223
  }
203
- if (!config.api) {
204
- throw new Error("[Blinker] API endpoint is required");
205
- }
206
224
  this.config = {
207
225
  captureErrors: true,
208
226
  captureRejections: true,
209
227
  debug: false,
210
228
  ...config
211
229
  };
230
+ this.filters = {
231
+ ignoreHttpCodes: (_b = (_a = config.filters) == null ? void 0 : _a.ignoreHttpCodes) != null ? _b : DEFAULT_FILTERS.ignoreHttpCodes,
232
+ ignoreErrorTypes: (_d = (_c = config.filters) == null ? void 0 : _c.ignoreErrorTypes) != null ? _d : DEFAULT_FILTERS.ignoreErrorTypes,
233
+ ignoreMessagePatterns: (_f = (_e = config.filters) == null ? void 0 : _e.ignoreMessagePatterns) != null ? _f : DEFAULT_FILTERS.ignoreMessagePatterns,
234
+ captureAll: (_h = (_g = config.filters) == null ? void 0 : _g.captureAll) != null ? _h : DEFAULT_FILTERS.captureAll
235
+ };
236
+ if (this.config.debug) {
237
+ console.log("[Blinker] Filters configured:", this.filters);
238
+ }
212
239
  if (this.config.captureErrors || this.config.captureRejections) {
213
240
  setupErrorHandlers(
214
241
  (type, message, payload) => {
215
- this.track(type, message, payload);
242
+ var _a2;
243
+ if (this.shouldCapture(message, payload == null ? void 0 : payload.errorType)) {
244
+ this.track(type, message, payload);
245
+ } else if ((_a2 = this.config) == null ? void 0 : _a2.debug) {
246
+ console.log("[Blinker] Error filtered out:", message);
247
+ }
216
248
  },
217
249
  {
218
250
  captureErrors: this.config.captureErrors,
@@ -226,6 +258,41 @@ var Blinker = class {
226
258
  console.log("[Blinker] SDK initialized successfully");
227
259
  }
228
260
  }
261
+ /**
262
+ * Check if an error should be captured based on filter settings
263
+ * @param message Error message
264
+ * @param errorType Optional JS error type (e.g., 'TypeError')
265
+ * @param httpCode Optional HTTP status code
266
+ * @returns true if the error should be captured, false if filtered out
267
+ */
268
+ shouldCapture(message, errorType, httpCode) {
269
+ if (this.filters.captureAll) {
270
+ return true;
271
+ }
272
+ if (httpCode !== void 0 && this.filters.ignoreHttpCodes.includes(httpCode)) {
273
+ return false;
274
+ }
275
+ if (errorType && this.filters.ignoreErrorTypes.includes(errorType)) {
276
+ return false;
277
+ }
278
+ for (const pattern of this.filters.ignoreMessagePatterns) {
279
+ if (message.toLowerCase().includes(pattern.toLowerCase())) {
280
+ return false;
281
+ }
282
+ }
283
+ if (httpCode === void 0) {
284
+ const httpCodeMatch = message.match(/(?:HTTP\s*|status[:\s]*)?(\d{3})(?:\s|$|:)/i);
285
+ if (httpCodeMatch) {
286
+ const extractedCode = parseInt(httpCodeMatch[1], 10);
287
+ if (extractedCode >= 100 && extractedCode < 600) {
288
+ if (this.filters.ignoreHttpCodes.includes(extractedCode)) {
289
+ return false;
290
+ }
291
+ }
292
+ }
293
+ }
294
+ return true;
295
+ }
229
296
  /**
230
297
  * Track a custom event
231
298
  * @param type Event type (e.g., 'click', 'pageview', 'custom')
@@ -248,15 +315,24 @@ var Blinker = class {
248
315
  url: typeof window !== "undefined" ? window.location.href : void 0,
249
316
  userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0
250
317
  };
251
- return sendEvent(this.config.api, this.config.token, event, this.config.debug);
318
+ return sendEvent(BLINKER_API, this.config.token, event, this.config.debug);
252
319
  }
253
320
  /**
254
321
  * Track an error manually
255
322
  * @param error Error object or message
256
- * @param additionalPayload Optional additional data
323
+ * @param additionalPayload Optional additional data (can include httpCode for filtering)
257
324
  */
258
325
  captureError(error, additionalPayload) {
326
+ var _a;
259
327
  const message = error instanceof Error ? error.message : error;
328
+ const errorType = error instanceof Error ? error.name : void 0;
329
+ const httpCode = additionalPayload == null ? void 0 : additionalPayload.httpCode;
330
+ if (!this.shouldCapture(message, errorType, httpCode)) {
331
+ if ((_a = this.config) == null ? void 0 : _a.debug) {
332
+ console.log("[Blinker] Error filtered out:", { message, errorType, httpCode });
333
+ }
334
+ return Promise.resolve({ success: true, error: "Filtered out by settings" });
335
+ }
260
336
  const payload = {
261
337
  ...additionalPayload
262
338
  };
@@ -302,10 +378,17 @@ var Blinker = class {
302
378
  teardownErrorHandlers();
303
379
  this.config = null;
304
380
  this.initialized = false;
381
+ this.filters = { ...DEFAULT_FILTERS };
305
382
  if (wasDebug) {
306
383
  console.log("[Blinker] SDK destroyed");
307
384
  }
308
385
  }
386
+ /**
387
+ * Get current filter settings
388
+ */
389
+ getFilters() {
390
+ return { ...this.filters };
391
+ }
309
392
  };
310
393
 
311
394
  // src/index.ts
package/dist/index.d.ts CHANGED
@@ -3,25 +3,33 @@
3
3
  * Universal JavaScript SDK for error tracking and event capture
4
4
  *
5
5
  * @example
6
+ * // Minimal setup - just pass your token!
6
7
  * import { blinker } from 'blinker-sdk';
7
8
  *
8
- * blinker.init({
9
- * token: 'your-token',
10
- * api: 'https://api.blinker.io'
11
- * });
9
+ * blinker.init({ token: 'your-token' });
12
10
  *
11
+ * // That's it! Errors are now automatically captured.
12
+ * // ✅ Ignores 401/403 errors by default
13
+ * // ✅ Filters out common browser noise
14
+ *
15
+ * @example
13
16
  * // Track custom events
14
17
  * blinker.track('click', 'Button clicked', { buttonId: 'submit' });
15
18
  *
16
- * // Track errors manually
17
- * blinker.captureError(new Error('Something went wrong'));
18
- *
19
- * // Track page views
20
- * blinker.trackPageView();
19
+ * @example
20
+ * // With custom filters (for advanced users)
21
+ * blinker.init({
22
+ * token: 'your-token',
23
+ * filters: {
24
+ * ignoreHttpCodes: [401], // Only ignore 401
25
+ * captureAll: false // Respect filters
26
+ * }
27
+ * });
21
28
  */
22
- import { Blinker } from './Blinker';
23
- export type { BlinkerConfig, BlinkerEvent, BlinkerEventInternal, BlinkerErrorPayload, SendResult } from './types';
29
+ import { Blinker, DEFAULT_FILTERS } from './Blinker';
30
+ export type { BlinkerConfig, BlinkerEvent, BlinkerEventInternal, BlinkerErrorPayload, SendResult, FilterSettings } from './types';
24
31
  export { Blinker };
32
+ export { DEFAULT_FILTERS };
25
33
  declare const blinker: Blinker;
26
34
  export { blinker };
27
35
  export default blinker;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACX,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,QAAA,MAAM,OAAO,SAAgB,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGrD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,OAAO,EAAE,eAAe,EAAE,CAAC;AAG3B,QAAA,MAAM,OAAO,SAAgB,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,eAAe,OAAO,CAAC"}
package/dist/index.esm.js CHANGED
@@ -153,16 +153,36 @@ function teardownErrorHandlers() {
153
153
  }
154
154
 
155
155
  // src/Blinker.ts
156
+ var BLINKER_API = "https://api.blinker.live";
157
+ var DEFAULT_FILTERS = {
158
+ // Auth/permission errors are usually expected behavior, not bugs
159
+ ignoreHttpCodes: [401, 403],
160
+ // All JS error types are captured by default
161
+ ignoreErrorTypes: [],
162
+ // Common benign browser errors that aren't actionable
163
+ ignoreMessagePatterns: [
164
+ "ResizeObserver loop",
165
+ // Common benign browser error
166
+ "Script error",
167
+ // Cross-origin script errors (no useful info)
168
+ "ResizeObserver loop completed"
169
+ // Another variant of ResizeObserver
170
+ ],
171
+ // By default, respect the filters
172
+ captureAll: false
173
+ };
156
174
  var Blinker = class {
157
175
  constructor() {
158
176
  this.config = null;
159
177
  this.initialized = false;
178
+ this.filters = { ...DEFAULT_FILTERS };
160
179
  }
161
180
  /**
162
181
  * Initialize the Blinker SDK
163
182
  * @param config Configuration options
164
183
  */
165
184
  init(config) {
185
+ var _a, _b, _c, _d, _e, _f, _g, _h;
166
186
  if (this.initialized) {
167
187
  if (config.debug) {
168
188
  console.warn("[Blinker] SDK already initialized");
@@ -172,19 +192,30 @@ var Blinker = class {
172
192
  if (!config.token) {
173
193
  throw new Error("[Blinker] Token is required");
174
194
  }
175
- if (!config.api) {
176
- throw new Error("[Blinker] API endpoint is required");
177
- }
178
195
  this.config = {
179
196
  captureErrors: true,
180
197
  captureRejections: true,
181
198
  debug: false,
182
199
  ...config
183
200
  };
201
+ this.filters = {
202
+ ignoreHttpCodes: (_b = (_a = config.filters) == null ? void 0 : _a.ignoreHttpCodes) != null ? _b : DEFAULT_FILTERS.ignoreHttpCodes,
203
+ ignoreErrorTypes: (_d = (_c = config.filters) == null ? void 0 : _c.ignoreErrorTypes) != null ? _d : DEFAULT_FILTERS.ignoreErrorTypes,
204
+ ignoreMessagePatterns: (_f = (_e = config.filters) == null ? void 0 : _e.ignoreMessagePatterns) != null ? _f : DEFAULT_FILTERS.ignoreMessagePatterns,
205
+ captureAll: (_h = (_g = config.filters) == null ? void 0 : _g.captureAll) != null ? _h : DEFAULT_FILTERS.captureAll
206
+ };
207
+ if (this.config.debug) {
208
+ console.log("[Blinker] Filters configured:", this.filters);
209
+ }
184
210
  if (this.config.captureErrors || this.config.captureRejections) {
185
211
  setupErrorHandlers(
186
212
  (type, message, payload) => {
187
- this.track(type, message, payload);
213
+ var _a2;
214
+ if (this.shouldCapture(message, payload == null ? void 0 : payload.errorType)) {
215
+ this.track(type, message, payload);
216
+ } else if ((_a2 = this.config) == null ? void 0 : _a2.debug) {
217
+ console.log("[Blinker] Error filtered out:", message);
218
+ }
188
219
  },
189
220
  {
190
221
  captureErrors: this.config.captureErrors,
@@ -198,6 +229,41 @@ var Blinker = class {
198
229
  console.log("[Blinker] SDK initialized successfully");
199
230
  }
200
231
  }
232
+ /**
233
+ * Check if an error should be captured based on filter settings
234
+ * @param message Error message
235
+ * @param errorType Optional JS error type (e.g., 'TypeError')
236
+ * @param httpCode Optional HTTP status code
237
+ * @returns true if the error should be captured, false if filtered out
238
+ */
239
+ shouldCapture(message, errorType, httpCode) {
240
+ if (this.filters.captureAll) {
241
+ return true;
242
+ }
243
+ if (httpCode !== void 0 && this.filters.ignoreHttpCodes.includes(httpCode)) {
244
+ return false;
245
+ }
246
+ if (errorType && this.filters.ignoreErrorTypes.includes(errorType)) {
247
+ return false;
248
+ }
249
+ for (const pattern of this.filters.ignoreMessagePatterns) {
250
+ if (message.toLowerCase().includes(pattern.toLowerCase())) {
251
+ return false;
252
+ }
253
+ }
254
+ if (httpCode === void 0) {
255
+ const httpCodeMatch = message.match(/(?:HTTP\s*|status[:\s]*)?(\d{3})(?:\s|$|:)/i);
256
+ if (httpCodeMatch) {
257
+ const extractedCode = parseInt(httpCodeMatch[1], 10);
258
+ if (extractedCode >= 100 && extractedCode < 600) {
259
+ if (this.filters.ignoreHttpCodes.includes(extractedCode)) {
260
+ return false;
261
+ }
262
+ }
263
+ }
264
+ }
265
+ return true;
266
+ }
201
267
  /**
202
268
  * Track a custom event
203
269
  * @param type Event type (e.g., 'click', 'pageview', 'custom')
@@ -220,15 +286,24 @@ var Blinker = class {
220
286
  url: typeof window !== "undefined" ? window.location.href : void 0,
221
287
  userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0
222
288
  };
223
- return sendEvent(this.config.api, this.config.token, event, this.config.debug);
289
+ return sendEvent(BLINKER_API, this.config.token, event, this.config.debug);
224
290
  }
225
291
  /**
226
292
  * Track an error manually
227
293
  * @param error Error object or message
228
- * @param additionalPayload Optional additional data
294
+ * @param additionalPayload Optional additional data (can include httpCode for filtering)
229
295
  */
230
296
  captureError(error, additionalPayload) {
297
+ var _a;
231
298
  const message = error instanceof Error ? error.message : error;
299
+ const errorType = error instanceof Error ? error.name : void 0;
300
+ const httpCode = additionalPayload == null ? void 0 : additionalPayload.httpCode;
301
+ if (!this.shouldCapture(message, errorType, httpCode)) {
302
+ if ((_a = this.config) == null ? void 0 : _a.debug) {
303
+ console.log("[Blinker] Error filtered out:", { message, errorType, httpCode });
304
+ }
305
+ return Promise.resolve({ success: true, error: "Filtered out by settings" });
306
+ }
232
307
  const payload = {
233
308
  ...additionalPayload
234
309
  };
@@ -274,10 +349,17 @@ var Blinker = class {
274
349
  teardownErrorHandlers();
275
350
  this.config = null;
276
351
  this.initialized = false;
352
+ this.filters = { ...DEFAULT_FILTERS };
277
353
  if (wasDebug) {
278
354
  console.log("[Blinker] SDK destroyed");
279
355
  }
280
356
  }
357
+ /**
358
+ * Get current filter settings
359
+ */
360
+ getFilters() {
361
+ return { ...this.filters };
362
+ }
281
363
  };
282
364
 
283
365
  // src/index.ts
@@ -285,6 +367,7 @@ var blinker = new Blinker();
285
367
  var index_default = blinker;
286
368
  export {
287
369
  Blinker,
370
+ DEFAULT_FILTERS,
288
371
  blinker,
289
372
  index_default as default
290
373
  };
package/dist/types.d.ts CHANGED
@@ -1,20 +1,49 @@
1
1
  /**
2
2
  * Blinker SDK Types
3
3
  */
4
+ /**
5
+ * Filter settings for controlling which errors are captured
6
+ * All settings are optional and come with sensible defaults
7
+ */
8
+ export interface FilterSettings {
9
+ /**
10
+ * HTTP status codes to ignore (not capture)
11
+ * Default: [401, 403] - Auth/permission errors are usually expected, not bugs
12
+ */
13
+ ignoreHttpCodes?: number[];
14
+ /**
15
+ * JavaScript error types to ignore (e.g., 'TypeError', 'SyntaxError')
16
+ * Default: [] - All error types are captured by default
17
+ */
18
+ ignoreErrorTypes?: string[];
19
+ /**
20
+ * Message patterns to ignore (substring matching)
21
+ * Default: ['ResizeObserver loop', 'Script error'] - Common benign browser errors
22
+ */
23
+ ignoreMessagePatterns?: string[];
24
+ /**
25
+ * When true, disables ALL filters and captures everything
26
+ * Default: false
27
+ */
28
+ captureAll?: boolean;
29
+ }
4
30
  /**
5
31
  * Configuration options for initializing the Blinker SDK
6
32
  */
7
33
  export interface BlinkerConfig {
8
- /** The authentication token for the Blinker API */
34
+ /** The authentication token for the Blinker API (REQUIRED) */
9
35
  token: string;
10
- /** The base URL of the Blinker API endpoint */
11
- api: string;
12
36
  /** Enable automatic error capture (default: true) */
13
37
  captureErrors?: boolean;
14
38
  /** Enable automatic unhandled rejection capture (default: true) */
15
39
  captureRejections?: boolean;
16
40
  /** Enable debug mode for logging (default: false) */
17
41
  debug?: boolean;
42
+ /**
43
+ * Filter settings for controlling which errors are captured
44
+ * By default, ignores common non-bug errors like 401, 403, ResizeObserver, etc.
45
+ */
46
+ filters?: FilterSettings;
18
47
  }
19
48
  /**
20
49
  * Event payload to be sent to the Blinker API
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAClE,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAClE,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blinker-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Universal JavaScript SDK for error tracking and event capture - works with any framework",
5
5
  "author": "Blinker",
6
6
  "license": "MIT",
@@ -63,11 +63,10 @@
63
63
  },
64
64
  "repository": {
65
65
  "type": "git",
66
- "url": "https://github.com/blinker/blinker-sdk.git"
66
+ "url": "git+https://github.com/blinker/blinker-sdk.git"
67
67
  },
68
68
  "bugs": {
69
69
  "url": "https://github.com/blinker/blinker-sdk/issues"
70
70
  },
71
71
  "homepage": "https://github.com/blinker/blinker-sdk#readme"
72
72
  }
73
-