@retrace-kit/sdk 0.0.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/README.md +49 -0
- package/dist/capture.d.ts +9 -0
- package/dist/config.d.ts +15 -0
- package/dist/globalHandlers.d.ts +2 -0
- package/dist/index.cjs +187 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +146 -0
- package/dist/transport.d.ts +9 -0
- package/dist/types.d.ts +26 -0
- package/dist/umd/index.js +188 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @bug-catcher/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Bug Catcher, built with [Rslib](https://rslib.rs/) (Rsbuild).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bug-catcher/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### ESM (Node.js / bundlers)
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { squared } from '@bug-catcher/sdk';
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### CommonJS
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
const { squared } = require('@bug-catcher/sdk');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### UMD (browser)
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<script src="https://unpkg.com/@bug-catcher/sdk/dist/umd/index.js"></script>
|
|
29
|
+
<script>
|
|
30
|
+
BugCatcher.squared(4); // 16
|
|
31
|
+
</script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install
|
|
38
|
+
npm run dev # watch mode
|
|
39
|
+
npm run build # production build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Build outputs:
|
|
43
|
+
|
|
44
|
+
| Format | Path |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| ESM | `dist/index.js` |
|
|
47
|
+
| CommonJS | `dist/index.cjs` |
|
|
48
|
+
| UMD | `dist/umd/index.js` |
|
|
49
|
+
| Types | `dist/index.d.ts` |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IngestErrorEventPayload } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Build a backend-aligned payload from an error, current config defaults, and optional overrides.
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildPayloadFromError(error: unknown, config: {
|
|
6
|
+
release?: string;
|
|
7
|
+
environment?: string;
|
|
8
|
+
}, context?: Partial<IngestErrorEventPayload>): IngestErrorEventPayload;
|
|
9
|
+
export declare function captureException(error: unknown, context?: Partial<IngestErrorEventPayload>): void;
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BugCatcherConfig } from './types';
|
|
2
|
+
type InternalConfig = {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
endpoint: string;
|
|
5
|
+
release?: string;
|
|
6
|
+
environment?: string;
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Initialize SDK configuration and global error handlers.
|
|
11
|
+
*/
|
|
12
|
+
export declare function init(config: BugCatcherConfig): void;
|
|
13
|
+
export declare function getCurrentConfig(): InternalConfig | null;
|
|
14
|
+
export declare function isCaptureEnabled(): boolean;
|
|
15
|
+
export {};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
31
|
+
captureException: ()=>captureException,
|
|
32
|
+
init: ()=>init
|
|
33
|
+
});
|
|
34
|
+
function sendErrorEvent(payload, config) {
|
|
35
|
+
(async ()=>{
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(config.endpoint, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: {
|
|
40
|
+
'Content-Type': 'application/json',
|
|
41
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify(payload)
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok) console.warn(`[bug-catcher sdk] failed to send error event: HTTP ${response.status}`);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error('[bug-catcher sdk] failed to send error event:', err);
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
}
|
|
51
|
+
function getBrowserUrl() {
|
|
52
|
+
try {
|
|
53
|
+
const href = globalThis.window?.location?.href;
|
|
54
|
+
if (href) return href;
|
|
55
|
+
} catch {}
|
|
56
|
+
}
|
|
57
|
+
function getBrowserUserAgent() {
|
|
58
|
+
try {
|
|
59
|
+
const userAgent = globalThis.navigator?.userAgent;
|
|
60
|
+
if (userAgent) return userAgent;
|
|
61
|
+
} catch {}
|
|
62
|
+
}
|
|
63
|
+
function extractMessage(error) {
|
|
64
|
+
if (error instanceof Error && error.message) return error.message;
|
|
65
|
+
if ('string' == typeof error && error) return error;
|
|
66
|
+
if (null != error) try {
|
|
67
|
+
const value = String(error);
|
|
68
|
+
if (value) return value;
|
|
69
|
+
} catch {}
|
|
70
|
+
return 'Unknown error';
|
|
71
|
+
}
|
|
72
|
+
function extractStacktrace(error) {
|
|
73
|
+
if (error instanceof Error && error.stack) return error.stack;
|
|
74
|
+
return 'No stacktrace available';
|
|
75
|
+
}
|
|
76
|
+
function buildPayloadFromError(error, config, context) {
|
|
77
|
+
const payload = {
|
|
78
|
+
timestamp: new Date().toISOString(),
|
|
79
|
+
message: extractMessage(error),
|
|
80
|
+
stacktrace: extractStacktrace(error),
|
|
81
|
+
url: getBrowserUrl(),
|
|
82
|
+
release: config.release,
|
|
83
|
+
environment: config.environment,
|
|
84
|
+
userAgent: getBrowserUserAgent()
|
|
85
|
+
};
|
|
86
|
+
if (!context) return payload;
|
|
87
|
+
return {
|
|
88
|
+
...payload,
|
|
89
|
+
...context
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function captureException(error, context) {
|
|
93
|
+
try {
|
|
94
|
+
const cfg = getCurrentConfig();
|
|
95
|
+
if (!cfg?.enabled || !cfg.apiKey) return;
|
|
96
|
+
const payload = buildPayloadFromError(error, cfg, context);
|
|
97
|
+
sendErrorEvent(payload, cfg);
|
|
98
|
+
} catch {}
|
|
99
|
+
}
|
|
100
|
+
let errorListener = null;
|
|
101
|
+
let rejectionListener = null;
|
|
102
|
+
function getBrowserWindow() {
|
|
103
|
+
try {
|
|
104
|
+
const win = globalThis.window;
|
|
105
|
+
if (win && 'function' == typeof win.addEventListener) return win;
|
|
106
|
+
} catch {}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function unregisterGlobalHandlers() {
|
|
110
|
+
const win = getBrowserWindow();
|
|
111
|
+
if (!win) return;
|
|
112
|
+
if (errorListener) {
|
|
113
|
+
win.removeEventListener('error', errorListener);
|
|
114
|
+
errorListener = null;
|
|
115
|
+
}
|
|
116
|
+
if (rejectionListener) {
|
|
117
|
+
win.removeEventListener('unhandledrejection', rejectionListener);
|
|
118
|
+
rejectionListener = null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function registerGlobalHandlers() {
|
|
122
|
+
const win = getBrowserWindow();
|
|
123
|
+
if (!win) return;
|
|
124
|
+
errorListener = (event)=>{
|
|
125
|
+
try {
|
|
126
|
+
const e = event;
|
|
127
|
+
const target = e.target;
|
|
128
|
+
if (target && target !== win && !e.error) return;
|
|
129
|
+
const error = e.error instanceof Error ? e.error : new Error(e.message || 'Unknown error');
|
|
130
|
+
captureException(error);
|
|
131
|
+
} catch {}
|
|
132
|
+
};
|
|
133
|
+
rejectionListener = (event)=>{
|
|
134
|
+
try {
|
|
135
|
+
const reason = event.reason;
|
|
136
|
+
captureException(reason);
|
|
137
|
+
} catch {}
|
|
138
|
+
};
|
|
139
|
+
win.addEventListener('error', errorListener);
|
|
140
|
+
win.addEventListener('unhandledrejection', rejectionListener);
|
|
141
|
+
}
|
|
142
|
+
let currentConfig = null;
|
|
143
|
+
let warnedAboutMissingApiKey = false;
|
|
144
|
+
function normalizeEndpoint(endpoint) {
|
|
145
|
+
return endpoint?.trim() ? endpoint : '/api/error-events';
|
|
146
|
+
}
|
|
147
|
+
function init(config) {
|
|
148
|
+
const endpoint = normalizeEndpoint(config?.endpoint);
|
|
149
|
+
const rawApiKey = config?.apiKey;
|
|
150
|
+
const apiKey = 'string' == typeof rawApiKey ? rawApiKey.trim() : '';
|
|
151
|
+
const enabledFromConfig = config?.enabled !== false;
|
|
152
|
+
unregisterGlobalHandlers();
|
|
153
|
+
if (!apiKey) {
|
|
154
|
+
if (!warnedAboutMissingApiKey) {
|
|
155
|
+
warnedAboutMissingApiKey = true;
|
|
156
|
+
console.warn('[bug-catcher sdk] init({ apiKey }) requires a non-blank apiKey; event sending will be disabled.');
|
|
157
|
+
}
|
|
158
|
+
currentConfig = {
|
|
159
|
+
apiKey: '',
|
|
160
|
+
endpoint,
|
|
161
|
+
release: config?.release,
|
|
162
|
+
environment: config?.environment,
|
|
163
|
+
enabled: false
|
|
164
|
+
};
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
currentConfig = {
|
|
168
|
+
apiKey,
|
|
169
|
+
endpoint,
|
|
170
|
+
release: config?.release,
|
|
171
|
+
environment: config?.environment,
|
|
172
|
+
enabled: enabledFromConfig
|
|
173
|
+
};
|
|
174
|
+
if (enabledFromConfig) registerGlobalHandlers();
|
|
175
|
+
}
|
|
176
|
+
function getCurrentConfig() {
|
|
177
|
+
return currentConfig;
|
|
178
|
+
}
|
|
179
|
+
exports.captureException = __webpack_exports__.captureException;
|
|
180
|
+
exports.init = __webpack_exports__.init;
|
|
181
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
182
|
+
"captureException",
|
|
183
|
+
"init"
|
|
184
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
185
|
+
Object.defineProperty(exports, '__esModule', {
|
|
186
|
+
value: true
|
|
187
|
+
});
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
function sendErrorEvent(payload, config) {
|
|
2
|
+
(async ()=>{
|
|
3
|
+
try {
|
|
4
|
+
const response = await fetch(config.endpoint, {
|
|
5
|
+
method: 'POST',
|
|
6
|
+
headers: {
|
|
7
|
+
'Content-Type': 'application/json',
|
|
8
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
9
|
+
},
|
|
10
|
+
body: JSON.stringify(payload)
|
|
11
|
+
});
|
|
12
|
+
if (!response.ok) console.warn(`[bug-catcher sdk] failed to send error event: HTTP ${response.status}`);
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.error('[bug-catcher sdk] failed to send error event:', err);
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
17
|
+
}
|
|
18
|
+
function getBrowserUrl() {
|
|
19
|
+
try {
|
|
20
|
+
const href = globalThis.window?.location?.href;
|
|
21
|
+
if (href) return href;
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
function getBrowserUserAgent() {
|
|
25
|
+
try {
|
|
26
|
+
const userAgent = globalThis.navigator?.userAgent;
|
|
27
|
+
if (userAgent) return userAgent;
|
|
28
|
+
} catch {}
|
|
29
|
+
}
|
|
30
|
+
function extractMessage(error) {
|
|
31
|
+
if (error instanceof Error && error.message) return error.message;
|
|
32
|
+
if ('string' == typeof error && error) return error;
|
|
33
|
+
if (null != error) try {
|
|
34
|
+
const value = String(error);
|
|
35
|
+
if (value) return value;
|
|
36
|
+
} catch {}
|
|
37
|
+
return 'Unknown error';
|
|
38
|
+
}
|
|
39
|
+
function extractStacktrace(error) {
|
|
40
|
+
if (error instanceof Error && error.stack) return error.stack;
|
|
41
|
+
return 'No stacktrace available';
|
|
42
|
+
}
|
|
43
|
+
function buildPayloadFromError(error, config, context) {
|
|
44
|
+
const payload = {
|
|
45
|
+
timestamp: new Date().toISOString(),
|
|
46
|
+
message: extractMessage(error),
|
|
47
|
+
stacktrace: extractStacktrace(error),
|
|
48
|
+
url: getBrowserUrl(),
|
|
49
|
+
release: config.release,
|
|
50
|
+
environment: config.environment,
|
|
51
|
+
userAgent: getBrowserUserAgent()
|
|
52
|
+
};
|
|
53
|
+
if (!context) return payload;
|
|
54
|
+
return {
|
|
55
|
+
...payload,
|
|
56
|
+
...context
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function captureException(error, context) {
|
|
60
|
+
try {
|
|
61
|
+
const cfg = getCurrentConfig();
|
|
62
|
+
if (!cfg?.enabled || !cfg.apiKey) return;
|
|
63
|
+
const payload = buildPayloadFromError(error, cfg, context);
|
|
64
|
+
sendErrorEvent(payload, cfg);
|
|
65
|
+
} catch {}
|
|
66
|
+
}
|
|
67
|
+
let errorListener = null;
|
|
68
|
+
let rejectionListener = null;
|
|
69
|
+
function getBrowserWindow() {
|
|
70
|
+
try {
|
|
71
|
+
const win = globalThis.window;
|
|
72
|
+
if (win && 'function' == typeof win.addEventListener) return win;
|
|
73
|
+
} catch {}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function unregisterGlobalHandlers() {
|
|
77
|
+
const win = getBrowserWindow();
|
|
78
|
+
if (!win) return;
|
|
79
|
+
if (errorListener) {
|
|
80
|
+
win.removeEventListener('error', errorListener);
|
|
81
|
+
errorListener = null;
|
|
82
|
+
}
|
|
83
|
+
if (rejectionListener) {
|
|
84
|
+
win.removeEventListener('unhandledrejection', rejectionListener);
|
|
85
|
+
rejectionListener = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function registerGlobalHandlers() {
|
|
89
|
+
const win = getBrowserWindow();
|
|
90
|
+
if (!win) return;
|
|
91
|
+
errorListener = (event)=>{
|
|
92
|
+
try {
|
|
93
|
+
const e = event;
|
|
94
|
+
const target = e.target;
|
|
95
|
+
if (target && target !== win && !e.error) return;
|
|
96
|
+
const error = e.error instanceof Error ? e.error : new Error(e.message || 'Unknown error');
|
|
97
|
+
captureException(error);
|
|
98
|
+
} catch {}
|
|
99
|
+
};
|
|
100
|
+
rejectionListener = (event)=>{
|
|
101
|
+
try {
|
|
102
|
+
const reason = event.reason;
|
|
103
|
+
captureException(reason);
|
|
104
|
+
} catch {}
|
|
105
|
+
};
|
|
106
|
+
win.addEventListener('error', errorListener);
|
|
107
|
+
win.addEventListener('unhandledrejection', rejectionListener);
|
|
108
|
+
}
|
|
109
|
+
let currentConfig = null;
|
|
110
|
+
let warnedAboutMissingApiKey = false;
|
|
111
|
+
function normalizeEndpoint(endpoint) {
|
|
112
|
+
return endpoint?.trim() ? endpoint : '/api/error-events';
|
|
113
|
+
}
|
|
114
|
+
function init(config) {
|
|
115
|
+
const endpoint = normalizeEndpoint(config?.endpoint);
|
|
116
|
+
const rawApiKey = config?.apiKey;
|
|
117
|
+
const apiKey = 'string' == typeof rawApiKey ? rawApiKey.trim() : '';
|
|
118
|
+
const enabledFromConfig = config?.enabled !== false;
|
|
119
|
+
unregisterGlobalHandlers();
|
|
120
|
+
if (!apiKey) {
|
|
121
|
+
if (!warnedAboutMissingApiKey) {
|
|
122
|
+
warnedAboutMissingApiKey = true;
|
|
123
|
+
console.warn('[bug-catcher sdk] init({ apiKey }) requires a non-blank apiKey; event sending will be disabled.');
|
|
124
|
+
}
|
|
125
|
+
currentConfig = {
|
|
126
|
+
apiKey: '',
|
|
127
|
+
endpoint,
|
|
128
|
+
release: config?.release,
|
|
129
|
+
environment: config?.environment,
|
|
130
|
+
enabled: false
|
|
131
|
+
};
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
currentConfig = {
|
|
135
|
+
apiKey,
|
|
136
|
+
endpoint,
|
|
137
|
+
release: config?.release,
|
|
138
|
+
environment: config?.environment,
|
|
139
|
+
enabled: enabledFromConfig
|
|
140
|
+
};
|
|
141
|
+
if (enabledFromConfig) registerGlobalHandlers();
|
|
142
|
+
}
|
|
143
|
+
function getCurrentConfig() {
|
|
144
|
+
return currentConfig;
|
|
145
|
+
}
|
|
146
|
+
export { captureException, init };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IngestErrorEventPayload } from './types';
|
|
2
|
+
export type SendConfig = {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
endpoint: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* POST error payload to the configured endpoint. Never throws; logs failures to console.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sendErrorEvent(payload: IngestErrorEventPayload, config: SendConfig): void;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type BugCatcherConfig = {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
/**
|
|
4
|
+
* Endpoint that receives error events.
|
|
5
|
+
* Defaults to `POST /api/error-events` (relative to the current origin).
|
|
6
|
+
*/
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
release?: string;
|
|
9
|
+
environment?: string;
|
|
10
|
+
/**
|
|
11
|
+
* When false, no events will be sent (public API stays callable).
|
|
12
|
+
*/
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type IngestErrorEventPayload = {
|
|
16
|
+
/**
|
|
17
|
+
* ISO-8601 timestamp string. If omitted, the SDK will use "now" in later steps.
|
|
18
|
+
*/
|
|
19
|
+
timestamp?: string;
|
|
20
|
+
message: string;
|
|
21
|
+
stacktrace: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
release?: string;
|
|
24
|
+
environment?: string;
|
|
25
|
+
userAgent?: string;
|
|
26
|
+
};
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
(function(root, factory) {
|
|
2
|
+
if ('object' == typeof exports && 'object' == typeof module) module.exports = factory();
|
|
3
|
+
else if ('function' == typeof define && define.amd) define([], factory);
|
|
4
|
+
else if ('object' == typeof exports) exports["BugCatcher"] = factory();
|
|
5
|
+
else root["BugCatcher"] = factory();
|
|
6
|
+
})(globalThis, ()=>(()=>{
|
|
7
|
+
"use strict";
|
|
8
|
+
var __webpack_require__ = {};
|
|
9
|
+
(()=>{
|
|
10
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
11
|
+
var define1 = (defs, kind)=>{
|
|
12
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
[kind]: defs[key]
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
define1(getters, "get");
|
|
18
|
+
define1(values, "value");
|
|
19
|
+
};
|
|
20
|
+
})();
|
|
21
|
+
(()=>{
|
|
22
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
23
|
+
})();
|
|
24
|
+
(()=>{
|
|
25
|
+
__webpack_require__.r = (exports1)=>{
|
|
26
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
27
|
+
value: 'Module'
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
30
|
+
value: true
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
})();
|
|
34
|
+
var __webpack_exports__ = {};
|
|
35
|
+
__webpack_require__.r(__webpack_exports__);
|
|
36
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
37
|
+
captureException: ()=>captureException,
|
|
38
|
+
init: ()=>init
|
|
39
|
+
});
|
|
40
|
+
function sendErrorEvent(payload, config) {
|
|
41
|
+
(async ()=>{
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(config.endpoint, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(payload)
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) console.warn(`[bug-catcher sdk] failed to send error event: HTTP ${response.status}`);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error('[bug-catcher sdk] failed to send error event:', err);
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
}
|
|
57
|
+
function getBrowserUrl() {
|
|
58
|
+
try {
|
|
59
|
+
var _globalThis_window_location, _globalThis_window;
|
|
60
|
+
const href = null == (_globalThis_window = globalThis.window) ? void 0 : null == (_globalThis_window_location = _globalThis_window.location) ? void 0 : _globalThis_window_location.href;
|
|
61
|
+
if (href) return href;
|
|
62
|
+
} catch {}
|
|
63
|
+
}
|
|
64
|
+
function getBrowserUserAgent() {
|
|
65
|
+
try {
|
|
66
|
+
var _globalThis_navigator;
|
|
67
|
+
const userAgent = null == (_globalThis_navigator = globalThis.navigator) ? void 0 : _globalThis_navigator.userAgent;
|
|
68
|
+
if (userAgent) return userAgent;
|
|
69
|
+
} catch {}
|
|
70
|
+
}
|
|
71
|
+
function extractMessage(error) {
|
|
72
|
+
if (error instanceof Error && error.message) return error.message;
|
|
73
|
+
if ('string' == typeof error && error) return error;
|
|
74
|
+
if (null != error) try {
|
|
75
|
+
const value = String(error);
|
|
76
|
+
if (value) return value;
|
|
77
|
+
} catch {}
|
|
78
|
+
return 'Unknown error';
|
|
79
|
+
}
|
|
80
|
+
function extractStacktrace(error) {
|
|
81
|
+
if (error instanceof Error && error.stack) return error.stack;
|
|
82
|
+
return 'No stacktrace available';
|
|
83
|
+
}
|
|
84
|
+
function buildPayloadFromError(error, config, context) {
|
|
85
|
+
const payload = {
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
message: extractMessage(error),
|
|
88
|
+
stacktrace: extractStacktrace(error),
|
|
89
|
+
url: getBrowserUrl(),
|
|
90
|
+
release: config.release,
|
|
91
|
+
environment: config.environment,
|
|
92
|
+
userAgent: getBrowserUserAgent()
|
|
93
|
+
};
|
|
94
|
+
if (!context) return payload;
|
|
95
|
+
return {
|
|
96
|
+
...payload,
|
|
97
|
+
...context
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function captureException(error, context) {
|
|
101
|
+
try {
|
|
102
|
+
const cfg = getCurrentConfig();
|
|
103
|
+
if (!(null == cfg ? void 0 : cfg.enabled) || !cfg.apiKey) return;
|
|
104
|
+
const payload = buildPayloadFromError(error, cfg, context);
|
|
105
|
+
sendErrorEvent(payload, cfg);
|
|
106
|
+
} catch {}
|
|
107
|
+
}
|
|
108
|
+
let errorListener = null;
|
|
109
|
+
let rejectionListener = null;
|
|
110
|
+
function getBrowserWindow() {
|
|
111
|
+
try {
|
|
112
|
+
const win = globalThis.window;
|
|
113
|
+
if (win && 'function' == typeof win.addEventListener) return win;
|
|
114
|
+
} catch {}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
function unregisterGlobalHandlers() {
|
|
118
|
+
const win = getBrowserWindow();
|
|
119
|
+
if (!win) return;
|
|
120
|
+
if (errorListener) {
|
|
121
|
+
win.removeEventListener('error', errorListener);
|
|
122
|
+
errorListener = null;
|
|
123
|
+
}
|
|
124
|
+
if (rejectionListener) {
|
|
125
|
+
win.removeEventListener('unhandledrejection', rejectionListener);
|
|
126
|
+
rejectionListener = null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function registerGlobalHandlers() {
|
|
130
|
+
const win = getBrowserWindow();
|
|
131
|
+
if (!win) return;
|
|
132
|
+
errorListener = (event)=>{
|
|
133
|
+
try {
|
|
134
|
+
const e = event;
|
|
135
|
+
const target = e.target;
|
|
136
|
+
if (target && target !== win && !e.error) return;
|
|
137
|
+
const error = e.error instanceof Error ? e.error : new Error(e.message || 'Unknown error');
|
|
138
|
+
captureException(error);
|
|
139
|
+
} catch {}
|
|
140
|
+
};
|
|
141
|
+
rejectionListener = (event)=>{
|
|
142
|
+
try {
|
|
143
|
+
const reason = event.reason;
|
|
144
|
+
captureException(reason);
|
|
145
|
+
} catch {}
|
|
146
|
+
};
|
|
147
|
+
win.addEventListener('error', errorListener);
|
|
148
|
+
win.addEventListener('unhandledrejection', rejectionListener);
|
|
149
|
+
}
|
|
150
|
+
let currentConfig = null;
|
|
151
|
+
let warnedAboutMissingApiKey = false;
|
|
152
|
+
function normalizeEndpoint(endpoint) {
|
|
153
|
+
return (null == endpoint ? void 0 : endpoint.trim()) ? endpoint : '/api/error-events';
|
|
154
|
+
}
|
|
155
|
+
function init(config) {
|
|
156
|
+
const endpoint = normalizeEndpoint(null == config ? void 0 : config.endpoint);
|
|
157
|
+
const rawApiKey = null == config ? void 0 : config.apiKey;
|
|
158
|
+
const apiKey = 'string' == typeof rawApiKey ? rawApiKey.trim() : '';
|
|
159
|
+
const enabledFromConfig = (null == config ? void 0 : config.enabled) !== false;
|
|
160
|
+
unregisterGlobalHandlers();
|
|
161
|
+
if (!apiKey) {
|
|
162
|
+
if (!warnedAboutMissingApiKey) {
|
|
163
|
+
warnedAboutMissingApiKey = true;
|
|
164
|
+
console.warn('[bug-catcher sdk] init({ apiKey }) requires a non-blank apiKey; event sending will be disabled.');
|
|
165
|
+
}
|
|
166
|
+
currentConfig = {
|
|
167
|
+
apiKey: '',
|
|
168
|
+
endpoint,
|
|
169
|
+
release: null == config ? void 0 : config.release,
|
|
170
|
+
environment: null == config ? void 0 : config.environment,
|
|
171
|
+
enabled: false
|
|
172
|
+
};
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
currentConfig = {
|
|
176
|
+
apiKey,
|
|
177
|
+
endpoint,
|
|
178
|
+
release: null == config ? void 0 : config.release,
|
|
179
|
+
environment: null == config ? void 0 : config.environment,
|
|
180
|
+
enabled: enabledFromConfig
|
|
181
|
+
};
|
|
182
|
+
if (enabledFromConfig) registerGlobalHandlers();
|
|
183
|
+
}
|
|
184
|
+
function getCurrentConfig() {
|
|
185
|
+
return currentConfig;
|
|
186
|
+
}
|
|
187
|
+
return __webpack_exports__;
|
|
188
|
+
})());
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@retrace-kit/sdk",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Retrace-kit SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.cjs",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.cjs",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"browser": "./dist/umd/index.js",
|
|
17
|
+
"unpkg": "./dist/umd/index.js",
|
|
18
|
+
"jsdelivr": "./dist/umd/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rslib build",
|
|
26
|
+
"dev": "rslib build --watch",
|
|
27
|
+
"test": "tsc --noEmit",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@rslib/core": "^0.22.1",
|
|
32
|
+
"@types/node": "^24.13.1",
|
|
33
|
+
"typescript": "^6.0.3"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.12.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|