rusty-replay 1.0.6 → 1.0.7
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/dist/index.cjs +5 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
@@ -56,29 +56,13 @@ function startRecording() {
|
|
56
56
|
events = [];
|
57
57
|
(0, import_rrweb.record)({
|
58
58
|
emit(event) {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
events = events.slice(-MAX_EVENTS);
|
63
|
-
}
|
59
|
+
events.push(event);
|
60
|
+
if (events.length > MAX_EVENTS) {
|
61
|
+
events = events.slice(-MAX_EVENTS);
|
64
62
|
}
|
65
|
-
}
|
66
|
-
blockClass: "no-record",
|
67
|
-
ignoreClass: "ignore-recording",
|
68
|
-
maskTextClass: "mask-text",
|
69
|
-
maskAllInputs: true,
|
70
|
-
mousemoveWait: 100
|
63
|
+
}
|
71
64
|
});
|
72
65
|
}
|
73
|
-
function shouldCaptureEvent(event) {
|
74
|
-
if (event.type === 3) {
|
75
|
-
return Date.now() % 300 === 0;
|
76
|
-
}
|
77
|
-
if (event.type === 4) {
|
78
|
-
return Date.now() % 200 === 0;
|
79
|
-
}
|
80
|
-
return true;
|
81
|
-
}
|
82
66
|
function getRecordedEvents(beforeErrorSec = 30) {
|
83
67
|
const now = Date.now();
|
84
68
|
return events.filter((e) => now - e.timestamp < beforeErrorSec * 1e3);
|
@@ -90,7 +74,7 @@ var init_recorder = __esm({
|
|
90
74
|
init_cjs_shims();
|
91
75
|
import_rrweb = require("rrweb");
|
92
76
|
events = [];
|
93
|
-
MAX_EVENTS =
|
77
|
+
MAX_EVENTS = 1e3;
|
94
78
|
}
|
95
79
|
});
|
96
80
|
|
package/dist/index.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/cjs_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 300;\n\nexport function startRecording(): void {\n events = [];\n record({\n emit(event) {\n if (shouldCaptureEvent(event)) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n }\n },\n\n blockClass: 'no-record',\n ignoreClass: 'ignore-recording',\n maskTextClass: 'mask-text',\n maskAllInputs: true,\n mousemoveWait: 100,\n });\n}\n\nfunction shouldCaptureEvent(event: eventWithTime): boolean {\n // 마우스 움직임, 스크롤 등 빈번한 이벤트는 샘플링\n if (event.type === 3) {\n return Date.now() % 300 === 0;\n }\n\n // 스크롤 이벤트 샘플링\n if (event.type === 4) {\n return Date.now() % 200 === 0;\n }\n\n return true;\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record","axios"]}
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/cjs_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\n\nexport function startRecording() {\n events = [];\n record({\n emit(event) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n });\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record","axios"]}
|
package/dist/index.js
CHANGED
@@ -36,29 +36,13 @@ function startRecording() {
|
|
36
36
|
events = [];
|
37
37
|
record({
|
38
38
|
emit(event) {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
events = events.slice(-MAX_EVENTS);
|
43
|
-
}
|
39
|
+
events.push(event);
|
40
|
+
if (events.length > MAX_EVENTS) {
|
41
|
+
events = events.slice(-MAX_EVENTS);
|
44
42
|
}
|
45
|
-
}
|
46
|
-
blockClass: "no-record",
|
47
|
-
ignoreClass: "ignore-recording",
|
48
|
-
maskTextClass: "mask-text",
|
49
|
-
maskAllInputs: true,
|
50
|
-
mousemoveWait: 100
|
43
|
+
}
|
51
44
|
});
|
52
45
|
}
|
53
|
-
function shouldCaptureEvent(event) {
|
54
|
-
if (event.type === 3) {
|
55
|
-
return Date.now() % 300 === 0;
|
56
|
-
}
|
57
|
-
if (event.type === 4) {
|
58
|
-
return Date.now() % 200 === 0;
|
59
|
-
}
|
60
|
-
return true;
|
61
|
-
}
|
62
46
|
function getRecordedEvents(beforeErrorSec = 30) {
|
63
47
|
const now = Date.now();
|
64
48
|
return events.filter((e) => now - e.timestamp < beforeErrorSec * 1e3);
|
@@ -69,7 +53,7 @@ var init_recorder = __esm({
|
|
69
53
|
"use strict";
|
70
54
|
init_esm_shims();
|
71
55
|
events = [];
|
72
|
-
MAX_EVENTS =
|
56
|
+
MAX_EVENTS = 1e3;
|
73
57
|
}
|
74
58
|
});
|
75
59
|
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/esm_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 300;\n\nexport function startRecording(): void {\n events = [];\n record({\n emit(event) {\n if (shouldCaptureEvent(event)) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n }\n },\n\n blockClass: 'no-record',\n ignoreClass: 'ignore-recording',\n maskTextClass: 'mask-text',\n maskAllInputs: true,\n mousemoveWait: 100,\n });\n}\n\nfunction shouldCaptureEvent(event: eventWithTime): boolean {\n // 마우스 움직임, 스크롤 등 빈번한 이벤트는 샘플링\n if (event.type === 3) {\n return Date.now() % 300 === 0;\n }\n\n // 스크롤 이벤트 샘플링\n if (event.type === 4) {\n return Date.now() % 200 === 0;\n }\n\n return true;\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record"]}
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.4.0_jiti@2.4.2_postcss@8.5.3_typescript@5.8.3/node_modules/tsup/assets/esm_shims.js","../src/recorder.ts","../src/environment.ts","../src/error-batcher.ts","../src/handler.ts","../src/reporter.ts","../src/index.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport { fileURLToPath } from 'url'\nimport path from 'path'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import type { eventWithTime } from '@rrweb/types';\nimport { record } from 'rrweb';\n\nlet events: eventWithTime[] = [];\nconst MAX_EVENTS = 1000;\n\nexport function startRecording() {\n events = [];\n record({\n emit(event) {\n events.push(event);\n if (events.length > MAX_EVENTS) {\n events = events.slice(-MAX_EVENTS);\n }\n },\n });\n}\n\nexport function getRecordedEvents(beforeErrorSec = 30): eventWithTime[] {\n const now = Date.now();\n return events.filter((e) => now - e.timestamp < beforeErrorSec * 1000);\n}\n","export function getBrowserInfo() {\n const ua = navigator.userAgent;\n let browser = 'unknown',\n os = 'unknown';\n\n if (ua.includes('Firefox')) browser = 'Firefox';\n else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';\n else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';\n else if (ua.includes('Trident')) browser = 'IE';\n else if (ua.includes('Edge')) browser = 'Edge (Legacy)';\n else if (ua.includes('Edg')) browser = 'Edge';\n else if (ua.includes('Chrome')) browser = 'Chrome';\n else if (ua.includes('Safari')) browser = 'Safari';\n\n if (ua.includes('Windows')) os = 'Windows';\n else if (ua.includes('Mac')) os = 'macOS';\n else if (ua.includes('Linux')) os = 'Linux';\n else if (ua.includes('Android')) os = 'Android';\n else if (ua.includes('like Mac')) os = 'iOS';\n\n return { browser, os, userAgent: ua };\n}\n\nexport function getEnvironment(): 'development' | 'staging' | 'production' {\n if (process.env.NODE_ENV === 'development') return 'development';\n if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') return 'staging';\n return 'production';\n}\n","import axios from 'axios';\nimport type { BatcherOptions, BatchedEvent } from './reporter';\n\nexport class ErrorBatcher {\n private queue: BatchedEvent[] = [];\n private isFlushing = false;\n private flushTimer: number;\n private readonly apiKey: string;\n\n constructor(private opts: BatcherOptions) {\n this.apiKey = opts.apiKey;\n const interval = opts.flushIntervalMs ?? 3000;\n this.flushTimer = window.setInterval(() => this.flush(), interval);\n window.addEventListener('beforeunload', () => this.flushOnUnload());\n }\n\n public getApiKey(): string {\n return this.apiKey;\n }\n\n public capture(evt: Omit<BatchedEvent, 'id' | 'timestamp'>): string {\n const id = this.makeId();\n const timestamp = new Date().toISOString();\n const record: BatchedEvent = { id, timestamp, ...evt };\n\n if (this.queue.length >= (this.opts.maxBufferSize ?? 64)) {\n this.queue.shift();\n }\n this.queue.push(record);\n return id;\n }\n\n private async flush() {\n if (this.isFlushing || this.queue.length === 0) return;\n this.isFlushing = true;\n\n const batch = this.queue.splice(0, this.queue.length);\n try {\n await axios.post(\n this.opts.endpoint,\n { events: batch },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.opts.apiKey}`,\n },\n }\n );\n } catch {\n this.queue.unshift(...batch);\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushOnUnload() {\n if (!navigator.sendBeacon || this.queue.length === 0) return;\n const payload = JSON.stringify({ events: this.queue });\n navigator.sendBeacon(this.opts.endpoint, payload);\n }\n\n private makeId() {\n return 'xxxx-xxxx-4xxx-yxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n\n public destroy() {\n clearInterval(this.flushTimer);\n }\n}\n","import { captureException } from './reporter';\n\nexport function setupGlobalErrorHandler() {\n if ((window as any).__errorHandlerSetup) return;\n\n const origOnError = window.onerror;\n window.onerror = function thisWindowOnError(\n this: Window & WindowEventHandlers,\n message: string | Event,\n source?: string,\n lineno?: number,\n colno?: number,\n error?: Error\n ): boolean {\n origOnError?.call(this, message, source, lineno, colno, error);\n captureException(\n error ??\n new Error(typeof message === 'string' ? message : 'Unknown error')\n );\n return false;\n };\n\n const origOnUnhandledRejection = window.onunhandledrejection;\n window.onunhandledrejection = function thisWindowOnRejection(\n this: Window & WindowEventHandlers,\n event: PromiseRejectionEvent\n ): any {\n origOnUnhandledRejection?.call(this, event);\n const err =\n event.reason instanceof Error\n ? event.reason\n : new Error(JSON.stringify(event.reason));\n captureException(err);\n } as typeof window.onunhandledrejection;\n\n (window as any).__errorHandlerSetup = true;\n}\n","import { startRecording, getRecordedEvents } from './recorder';\nimport { getBrowserInfo, getEnvironment } from './environment';\nimport { ErrorBatcher } from './error-batcher';\n\nexport interface BatchedEvent {\n id: string;\n timestamp: string;\n message: string;\n stacktrace: string;\n replay: any[];\n environment: string;\n browser: string;\n os: string;\n userAgent: string;\n userId?: number;\n additionalInfo?: Record<string, any>;\n appVersion: string;\n apiKey: string;\n}\n\nexport interface BatcherOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n}\n\nexport interface InitOptions {\n endpoint: string;\n apiKey: string;\n flushIntervalMs?: number;\n maxBufferSize?: number;\n beforeErrorSec?: number;\n}\n\nlet batcher: ErrorBatcher;\nlet globalOpts: { beforeErrorSec: number } = { beforeErrorSec: 30 };\n\nexport function init(options: InitOptions) {\n startRecording();\n globalOpts.beforeErrorSec = options.beforeErrorSec ?? 30;\n batcher = new ErrorBatcher({\n endpoint: options.endpoint,\n apiKey: options.apiKey,\n flushIntervalMs: options.flushIntervalMs,\n maxBufferSize: options.maxBufferSize,\n });\n import('./handler.js').then((mod) => mod.setupGlobalErrorHandler());\n}\n\nexport function captureException(\n error: Error,\n additionalInfo?: Record<string, any>,\n userId?: number\n): string {\n const { browser, os, userAgent } = getBrowserInfo();\n const replay = getRecordedEvents(globalOpts.beforeErrorSec);\n return batcher.capture({\n message: error.message ?? '',\n stacktrace: error.stack ?? '',\n replay,\n environment: getEnvironment(),\n browser,\n os,\n userAgent,\n userId,\n additionalInfo,\n appVersion: '1.0.0',\n apiKey: batcher.getApiKey(),\n });\n}\n\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n info?: { additionalInfo?: Record<string, any>; userId?: number }\n): (...args: Parameters<T>) => ReturnType<T> {\n return (...args) => {\n try {\n return fn(...args);\n } catch (err) {\n if (err instanceof Error) {\n captureException(err, info?.additionalInfo, info?.userId);\n } else {\n captureException(\n new Error(String(err)),\n info?.additionalInfo,\n info?.userId\n );\n }\n throw err;\n }\n };\n}\n","export * from './reporter';\nexport { setupGlobalErrorHandler } from './handler';\nexport { startRecording, getRecordedEvents } from './recorder';\nexport { getBrowserInfo, getEnvironment } from './environment';\nexport { ErrorBatcher } from './error-batcher';\nexport type { BatchedEvent, InitOptions } from './reporter';\n"],"mappings":"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","names":["record"]}
|