@vybesec/sdk 0.1.0 → 0.1.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/dist/index.cjs +31 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -16
- package/dist/index.d.ts +48 -16
- package/dist/index.js +31 -19
- package/dist/index.js.map +1 -1
- package/dist/v1/sdk.js +1 -1
- package/dist/v1/sdk.js.map +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -303,37 +303,49 @@ var VybeSecSDK = class {
|
|
|
303
303
|
if (typeof window === "undefined" || !("XMLHttpRequest" in window)) return;
|
|
304
304
|
const sdk = this;
|
|
305
305
|
const proto = XMLHttpRequest.prototype;
|
|
306
|
-
if (proto.
|
|
307
|
-
proto.
|
|
306
|
+
if (proto.__vsPatched) return;
|
|
307
|
+
proto.__vsPatched = true;
|
|
308
308
|
const originalOpen = proto.open;
|
|
309
309
|
const originalSend = proto.send;
|
|
310
310
|
proto.open = function(method, url, async, user, password) {
|
|
311
311
|
const xhr = this;
|
|
312
|
-
xhr.
|
|
313
|
-
return originalOpen.call(
|
|
312
|
+
xhr.__vsMeta = { method, url: String(url) };
|
|
313
|
+
return originalOpen.call(
|
|
314
|
+
xhr,
|
|
315
|
+
method,
|
|
316
|
+
url,
|
|
317
|
+
async ?? true,
|
|
318
|
+
user ?? null,
|
|
319
|
+
password ?? null
|
|
320
|
+
);
|
|
314
321
|
};
|
|
315
322
|
proto.send = function(body) {
|
|
316
323
|
const xhr = this;
|
|
317
|
-
const meta = xhr.
|
|
324
|
+
const meta = xhr.__vsMeta;
|
|
318
325
|
const handleComplete = () => {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
try {
|
|
327
|
+
if (!sdk.config || !meta) return;
|
|
328
|
+
const status = xhr.status;
|
|
329
|
+
if (status >= 400 || status === 0) {
|
|
330
|
+
sdk.captureEvent({
|
|
331
|
+
type: "error",
|
|
332
|
+
message: `XHR failed with ${status || "network error"}`,
|
|
333
|
+
errorType: "HttpError",
|
|
334
|
+
requestUrl: meta.url,
|
|
335
|
+
requestMethod: meta.method,
|
|
336
|
+
responseStatus: status || void 0,
|
|
337
|
+
url: typeof window !== "undefined" ? window.location.href : void 0,
|
|
338
|
+
timestamp: Date.now()
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
} finally {
|
|
342
|
+
xhr.removeEventListener("loadend", handleComplete);
|
|
343
|
+
xhr.removeEventListener("error", handleComplete);
|
|
332
344
|
}
|
|
333
345
|
};
|
|
334
346
|
xhr.addEventListener("loadend", handleComplete);
|
|
335
347
|
xhr.addEventListener("error", handleComplete);
|
|
336
|
-
return originalSend.call(xhr, body
|
|
348
|
+
return originalSend.call(xhr, body);
|
|
337
349
|
};
|
|
338
350
|
}
|
|
339
351
|
trackNavigation() {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nexport type RawEvent = {\n type: \"error\" | \"warning\" | \"info\" | \"performance\" | \"custom\";\n message: string;\n stackTrace?: string;\n errorType?: string;\n url?: string;\n requestUrl?: string;\n requestMethod?: string;\n responseStatus?: number;\n sessionId?: string;\n userId?: string;\n timestamp: number;\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vwPatched?: boolean;\n __vwMeta?: { method: string; url: string };\n };\n\n if (proto.__vwPatched) return;\n proto.__vwPatched = true;\n\n const originalOpen = proto.open;\n const originalSend = proto.send;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vwMeta = { method, url: String(url) };\n return originalOpen.call(xhr, method, url, async ?? true, user ?? null, password ?? null);\n };\n\n proto.send = function (body?: Document | XMLHttpRequestBodyInit | null) {\n const xhr = this as typeof proto;\n const meta = xhr.__vwMeta;\n\n const handleComplete = () => {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n return originalSend.call(xhr, body ?? null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent } from \"@vybesec/types\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vsPatched?: boolean;\n __vsMeta?: { method: string; url: string };\n };\n\n if (proto.__vsPatched) return;\n proto.__vsPatched = true;\n\n const originalOpen = proto.open;\n // narrow the send signature to match what we'll call\n const originalSend = proto.send as (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null\n ) => void;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vsMeta = { method, url: String(url) };\n return originalOpen.call(\n xhr,\n method,\n url,\n async ?? true,\n user ?? null,\n password ?? null\n );\n };\n\n // Accept any here and cast when calling the native send to avoid\n // TypeScript diagnostics around BodyInit / ReadableStream mismatch.\n proto.send = function (body?: any) {\n const xhr = this as typeof proto;\n const meta = xhr.__vsMeta;\n\n const handleComplete = () => {\n try {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } finally {\n // clean up listeners to avoid leaks / duplicate reporting\n xhr.removeEventListener(\"loadend\", handleComplete);\n xhr.removeEventListener(\"error\", handleComplete);\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n // Cast to the native expected type to satisfy the method signature.\n return originalSend.call(xhr, body as Document | XMLHttpRequestBodyInit | null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const rawEventSchema: z.ZodObject<{
|
|
4
|
+
type: z.ZodEnum<["error", "warning", "info", "performance", "custom"]>;
|
|
5
|
+
message: z.ZodString;
|
|
6
|
+
stackTrace: z.ZodOptional<z.ZodString>;
|
|
7
|
+
errorType: z.ZodOptional<z.ZodString>;
|
|
8
|
+
url: z.ZodOptional<z.ZodString>;
|
|
9
|
+
requestUrl: z.ZodOptional<z.ZodString>;
|
|
10
|
+
requestMethod: z.ZodOptional<z.ZodString>;
|
|
11
|
+
responseStatus: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
14
|
+
timestamp: z.ZodNumber;
|
|
15
|
+
tags: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
type: "custom" | "error" | "warning" | "info" | "performance";
|
|
19
|
+
message: string;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
stackTrace?: string | undefined;
|
|
22
|
+
errorType?: string | undefined;
|
|
23
|
+
url?: string | undefined;
|
|
24
|
+
requestUrl?: string | undefined;
|
|
25
|
+
requestMethod?: string | undefined;
|
|
26
|
+
responseStatus?: number | undefined;
|
|
27
|
+
sessionId?: string | undefined;
|
|
28
|
+
userId?: string | undefined;
|
|
29
|
+
tags?: Record<string, string> | undefined;
|
|
30
|
+
extra?: Record<string, any> | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
type: "custom" | "error" | "warning" | "info" | "performance";
|
|
33
|
+
message: string;
|
|
34
|
+
timestamp: number;
|
|
35
|
+
stackTrace?: string | undefined;
|
|
36
|
+
errorType?: string | undefined;
|
|
37
|
+
url?: string | undefined;
|
|
38
|
+
requestUrl?: string | undefined;
|
|
39
|
+
requestMethod?: string | undefined;
|
|
40
|
+
responseStatus?: number | undefined;
|
|
41
|
+
sessionId?: string | undefined;
|
|
42
|
+
userId?: string | undefined;
|
|
43
|
+
tags?: Record<string, string> | undefined;
|
|
44
|
+
extra?: Record<string, any> | undefined;
|
|
45
|
+
}>;
|
|
46
|
+
type RawEvent = z.infer<typeof rawEventSchema>;
|
|
47
|
+
|
|
1
48
|
type VybeSecConfig = {
|
|
2
49
|
key: string;
|
|
3
50
|
environment?: "production" | "staging" | "development";
|
|
@@ -9,21 +56,6 @@ type VybeSecConfig = {
|
|
|
9
56
|
maxEventsPerMinute?: number;
|
|
10
57
|
ingestUrl?: string;
|
|
11
58
|
};
|
|
12
|
-
type RawEvent = {
|
|
13
|
-
type: "error" | "warning" | "info" | "performance" | "custom";
|
|
14
|
-
message: string;
|
|
15
|
-
stackTrace?: string;
|
|
16
|
-
errorType?: string;
|
|
17
|
-
url?: string;
|
|
18
|
-
requestUrl?: string;
|
|
19
|
-
requestMethod?: string;
|
|
20
|
-
responseStatus?: number;
|
|
21
|
-
sessionId?: string;
|
|
22
|
-
userId?: string;
|
|
23
|
-
timestamp: number;
|
|
24
|
-
tags?: Record<string, string>;
|
|
25
|
-
extra?: Record<string, unknown>;
|
|
26
|
-
};
|
|
27
59
|
declare class VybeSecSDK {
|
|
28
60
|
private config;
|
|
29
61
|
private buffer;
|
|
@@ -50,4 +82,4 @@ declare const init: (config: VybeSecConfig) => void;
|
|
|
50
82
|
declare const captureError: (error: unknown) => void;
|
|
51
83
|
declare const captureEvent: (event: RawEvent) => void;
|
|
52
84
|
|
|
53
|
-
export { type
|
|
85
|
+
export { type VybeSecConfig, VybeSecSDK, captureError, captureEvent, init, vybesec };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const rawEventSchema: z.ZodObject<{
|
|
4
|
+
type: z.ZodEnum<["error", "warning", "info", "performance", "custom"]>;
|
|
5
|
+
message: z.ZodString;
|
|
6
|
+
stackTrace: z.ZodOptional<z.ZodString>;
|
|
7
|
+
errorType: z.ZodOptional<z.ZodString>;
|
|
8
|
+
url: z.ZodOptional<z.ZodString>;
|
|
9
|
+
requestUrl: z.ZodOptional<z.ZodString>;
|
|
10
|
+
requestMethod: z.ZodOptional<z.ZodString>;
|
|
11
|
+
responseStatus: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
14
|
+
timestamp: z.ZodNumber;
|
|
15
|
+
tags: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
type: "custom" | "error" | "warning" | "info" | "performance";
|
|
19
|
+
message: string;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
stackTrace?: string | undefined;
|
|
22
|
+
errorType?: string | undefined;
|
|
23
|
+
url?: string | undefined;
|
|
24
|
+
requestUrl?: string | undefined;
|
|
25
|
+
requestMethod?: string | undefined;
|
|
26
|
+
responseStatus?: number | undefined;
|
|
27
|
+
sessionId?: string | undefined;
|
|
28
|
+
userId?: string | undefined;
|
|
29
|
+
tags?: Record<string, string> | undefined;
|
|
30
|
+
extra?: Record<string, any> | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
type: "custom" | "error" | "warning" | "info" | "performance";
|
|
33
|
+
message: string;
|
|
34
|
+
timestamp: number;
|
|
35
|
+
stackTrace?: string | undefined;
|
|
36
|
+
errorType?: string | undefined;
|
|
37
|
+
url?: string | undefined;
|
|
38
|
+
requestUrl?: string | undefined;
|
|
39
|
+
requestMethod?: string | undefined;
|
|
40
|
+
responseStatus?: number | undefined;
|
|
41
|
+
sessionId?: string | undefined;
|
|
42
|
+
userId?: string | undefined;
|
|
43
|
+
tags?: Record<string, string> | undefined;
|
|
44
|
+
extra?: Record<string, any> | undefined;
|
|
45
|
+
}>;
|
|
46
|
+
type RawEvent = z.infer<typeof rawEventSchema>;
|
|
47
|
+
|
|
1
48
|
type VybeSecConfig = {
|
|
2
49
|
key: string;
|
|
3
50
|
environment?: "production" | "staging" | "development";
|
|
@@ -9,21 +56,6 @@ type VybeSecConfig = {
|
|
|
9
56
|
maxEventsPerMinute?: number;
|
|
10
57
|
ingestUrl?: string;
|
|
11
58
|
};
|
|
12
|
-
type RawEvent = {
|
|
13
|
-
type: "error" | "warning" | "info" | "performance" | "custom";
|
|
14
|
-
message: string;
|
|
15
|
-
stackTrace?: string;
|
|
16
|
-
errorType?: string;
|
|
17
|
-
url?: string;
|
|
18
|
-
requestUrl?: string;
|
|
19
|
-
requestMethod?: string;
|
|
20
|
-
responseStatus?: number;
|
|
21
|
-
sessionId?: string;
|
|
22
|
-
userId?: string;
|
|
23
|
-
timestamp: number;
|
|
24
|
-
tags?: Record<string, string>;
|
|
25
|
-
extra?: Record<string, unknown>;
|
|
26
|
-
};
|
|
27
59
|
declare class VybeSecSDK {
|
|
28
60
|
private config;
|
|
29
61
|
private buffer;
|
|
@@ -50,4 +82,4 @@ declare const init: (config: VybeSecConfig) => void;
|
|
|
50
82
|
declare const captureError: (error: unknown) => void;
|
|
51
83
|
declare const captureEvent: (event: RawEvent) => void;
|
|
52
84
|
|
|
53
|
-
export { type
|
|
85
|
+
export { type VybeSecConfig, VybeSecSDK, captureError, captureEvent, init, vybesec };
|
package/dist/index.js
CHANGED
|
@@ -277,37 +277,49 @@ var VybeSecSDK = class {
|
|
|
277
277
|
if (typeof window === "undefined" || !("XMLHttpRequest" in window)) return;
|
|
278
278
|
const sdk = this;
|
|
279
279
|
const proto = XMLHttpRequest.prototype;
|
|
280
|
-
if (proto.
|
|
281
|
-
proto.
|
|
280
|
+
if (proto.__vsPatched) return;
|
|
281
|
+
proto.__vsPatched = true;
|
|
282
282
|
const originalOpen = proto.open;
|
|
283
283
|
const originalSend = proto.send;
|
|
284
284
|
proto.open = function(method, url, async, user, password) {
|
|
285
285
|
const xhr = this;
|
|
286
|
-
xhr.
|
|
287
|
-
return originalOpen.call(
|
|
286
|
+
xhr.__vsMeta = { method, url: String(url) };
|
|
287
|
+
return originalOpen.call(
|
|
288
|
+
xhr,
|
|
289
|
+
method,
|
|
290
|
+
url,
|
|
291
|
+
async ?? true,
|
|
292
|
+
user ?? null,
|
|
293
|
+
password ?? null
|
|
294
|
+
);
|
|
288
295
|
};
|
|
289
296
|
proto.send = function(body) {
|
|
290
297
|
const xhr = this;
|
|
291
|
-
const meta = xhr.
|
|
298
|
+
const meta = xhr.__vsMeta;
|
|
292
299
|
const handleComplete = () => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
300
|
+
try {
|
|
301
|
+
if (!sdk.config || !meta) return;
|
|
302
|
+
const status = xhr.status;
|
|
303
|
+
if (status >= 400 || status === 0) {
|
|
304
|
+
sdk.captureEvent({
|
|
305
|
+
type: "error",
|
|
306
|
+
message: `XHR failed with ${status || "network error"}`,
|
|
307
|
+
errorType: "HttpError",
|
|
308
|
+
requestUrl: meta.url,
|
|
309
|
+
requestMethod: meta.method,
|
|
310
|
+
responseStatus: status || void 0,
|
|
311
|
+
url: typeof window !== "undefined" ? window.location.href : void 0,
|
|
312
|
+
timestamp: Date.now()
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
} finally {
|
|
316
|
+
xhr.removeEventListener("loadend", handleComplete);
|
|
317
|
+
xhr.removeEventListener("error", handleComplete);
|
|
306
318
|
}
|
|
307
319
|
};
|
|
308
320
|
xhr.addEventListener("loadend", handleComplete);
|
|
309
321
|
xhr.addEventListener("error", handleComplete);
|
|
310
|
-
return originalSend.call(xhr, body
|
|
322
|
+
return originalSend.call(xhr, body);
|
|
311
323
|
};
|
|
312
324
|
}
|
|
313
325
|
trackNavigation() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nexport type RawEvent = {\n type: \"error\" | \"warning\" | \"info\" | \"performance\" | \"custom\";\n message: string;\n stackTrace?: string;\n errorType?: string;\n url?: string;\n requestUrl?: string;\n requestMethod?: string;\n responseStatus?: number;\n sessionId?: string;\n userId?: string;\n timestamp: number;\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vwPatched?: boolean;\n __vwMeta?: { method: string; url: string };\n };\n\n if (proto.__vwPatched) return;\n proto.__vwPatched = true;\n\n const originalOpen = proto.open;\n const originalSend = proto.send;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vwMeta = { method, url: String(url) };\n return originalOpen.call(xhr, method, url, async ?? true, user ?? null, password ?? null);\n };\n\n proto.send = function (body?: Document | XMLHttpRequestBodyInit | null) {\n const xhr = this as typeof proto;\n const meta = xhr.__vwMeta;\n\n const handleComplete = () => {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n return originalSend.call(xhr, body ?? null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],"mappings":";;;;;AAmCA,IAAM,qBAAqB;AAC3B,IAAM,cAAc;AAEpB,SAAS,eAAuB;AAC9B,MAAI;AACF,UAAM,WAAW,OAAO,aAAa,QAAQ,WAAW;AACxD,QAAI,SAAU,QAAO;AACrB,UAAM,OAAO,OAAO,WAAW;AAC/B,WAAO,aAAa,QAAQ,aAAa,IAAI;AAC7C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,OAAO,WAAW;AAAA,EAC3B;AACF;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,iBAAiB,MAAO,QAAO,MAAM,WAAW;AACpD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAwB;AAC5C,MAAI,iBAAiB,SAAS,MAAM,KAAM,QAAO,MAAM;AACvD,SAAO;AACT;AAEA,SAAS,cAAc,OAAoC;AACzD,MAAI,iBAAiB,MAAO,QAAO,MAAM;AACzC,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAoC;AAC9D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,SAAS;AACb,aAAW,WAAW,UAAU;AAC9B,aAAS,OAAO,QAAQ,SAAS,YAAY;AAAA,EAC/C;AACA,SAAO;AACT;AAEA,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AAExB,SAAS,WAAW,OAAgB,QAAQ,GAAY;AACtD,MAAI,SAAS,gBAAiB,QAAO;AACrC,MAAI,OAAO,UAAU,SAAU,QAAO,mBAAmB,KAAK,KAAK;AACnE,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,UAAU,WAAW,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC1D;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS;AACf,UAAM,OAAgC,CAAC;AACvC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,cAAc,KAAK,GAAG,GAAG;AAC3B,aAAK,GAAG,IAAI;AACZ;AAAA,MACF;AACA,WAAK,GAAG,IAAI,WAAW,OAAO,QAAQ,CAAC;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAA2B;AAC7C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,mBAAmB,MAAM,OAAO,KAAK,MAAM;AAAA,IACpD,YAAY,mBAAmB,MAAM,UAAU;AAAA,IAC/C,MAAM,MAAM,OAAQ,WAAW,MAAM,IAAI,IAA+B,MAAM;AAAA,IAC9E,OAAO,MAAM,QAAS,WAAW,MAAM,KAAK,IAAgC,MAAM;AAAA,EACpF;AACF;AAEO,IAAM,aAAN,MAAiB;AAAA,EAAjB;AACL,wBAAQ,UAA+B;AACvC,wBAAQ,UAAqB,CAAC;AAC9B,wBAAQ,mBAA4B,CAAC;AACrC,wBAAQ;AACR,wBAAQ;AACR,wBAAQ,gBAAe;AACvB,wBAAQ,cAAa;AAAA;AAAA,EAErB,KAAK,QAAuB;AAC1B,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,YAAY,OAAO,cAAc;AAAA,MACjC,WAAW,OAAO,aAAa;AAAA,MAC/B,oBAAoB,OAAO,sBAAsB;AAAA,MACjD,WAAW,OAAO,aAAa;AAAA,IACjC;AAEA,QAAI,OAAO,WAAW,YAAa;AAEnC,WAAO,iBAAiB,SAAS,CAAC,UAAU;AAC1C,WAAK,aAAa,MAAM,SAAS,MAAM,SAAS;AAAA,QAC9C,KAAK,MAAM;AAAA,MACb,CAAC;AAAA,IACH,CAAC;AAED,WAAO,iBAAiB,sBAAsB,CAAC,UAAU;AACvD,WAAK,aAAa,MAAM,MAAM;AAAA,IAChC,CAAC;AAED,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,gBAAgB;AAErB,WAAO,iBAAiB,oBAAoB,MAAM;AAChD,UAAI,SAAS,oBAAoB,UAAU;AACzC,aAAK,YAAY;AAAA,MACnB;AAAA,IACF,CAAC;AAED,QAAI,KAAK,YAAY;AACnB,aAAO,cAAc,KAAK,UAAU;AAAA,IACtC;AACA,QAAI,KAAK,YAAY;AACnB,aAAO,aAAa,KAAK,UAAU;AACnC,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,eAAe;AACpB,SAAK,aAAa,OAAO,YAAY,MAAM,KAAK,MAAM,GAAG,GAAI;AAAA,EAC/D;AAAA,EAEA,aAAa,OAAgB,SAAkC;AAC7D,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAE/B,UAAM,QAAkB,WAAW;AAAA,MACjC,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,MAC9B,YAAY,cAAc,KAAK;AAAA,MAC/B,WAAW,aAAa,KAAK;AAAA,MAC7B,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,MAC5D,WAAW,OAAO,WAAW,cAAc,aAAa,IAAI;AAAA,MAC5D,QAAQ,KAAK,OAAO;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,MACpB,MAAM;AAAA,QACJ,GAAI,WAAW,CAAC;AAAA,QAChB,UAAU,KAAK,OAAO,YAAY;AAAA,QAClC,aAAa,KAAK,OAAO,eAAe;AAAA,QACxC,SAAS,KAAK,OAAO,WAAW;AAAA,MAClC;AAAA,IACF,CAAC;AAED,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,aAAa,OAAiB;AAC5B,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAC/B,UAAM,WAAqB,WAAW;AAAA,MACpC,GAAG;AAAA,MACH,WAAW,MAAM,cAAc,OAAO,WAAW,cAAc,aAAa,IAAI;AAAA,MAChF,QAAQ,MAAM,UAAU,KAAK,OAAO;AAAA,MACpC,WAAW,MAAM,aAAa,KAAK,IAAI;AAAA,MACvC,MAAM;AAAA,QACJ,GAAI,MAAM,QAAQ,CAAC;AAAA,QACnB,UAAU,KAAK,OAAO,YAAY;AAAA,QAClC,aAAa,KAAK,OAAO,eAAe;AAAA,QACxC,SAAS,KAAK,OAAO,WAAW;AAAA,MAClC;AAAA,IACF,CAAC;AAED,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEQ,UAAU,OAAiB;AACjC,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,QAAI,aAAa,EAAG;AACpB,WAAO,KAAK,OAAO,UAAU,WAAW;AACtC,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,SAAK,OAAO,KAAK,KAAK;AACtB,QAAI,KAAK,OAAO,UAAU,IAAI;AAC5B,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ;AACpB,QAAI,CAAC,KAAK,UAAU,KAAK,WAAY;AACrC,QAAI,CAAC,KAAK,OAAO,OAAQ;AAEzB,SAAK,aAAa;AAClB,UAAM,SAAS,KAAK,OAAO,OAAO,CAAC;AAEnC,QAAI;AACF,YAAM,MAAM,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG,IAAI;AAAA,QACnE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,MAAM;AAAA,QAC3B,WAAW;AAAA,MACb,CAAC;AACD,WAAK,eAAe;AACpB,UAAI,KAAK,YAAY;AACnB,eAAO,aAAa,KAAK,UAAU;AACnC,aAAK,aAAa;AAAA,MACpB;AAAA,IACF,QAAQ;AACN,WAAK,OAAO,QAAQ,GAAG,MAAM;AAC7B,WAAK,cAAc;AAAA,IACrB,UAAE;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,cAAc;AACpB,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAO,OAAQ;AAEzC,UAAM,SAAS,KAAK,OAAO,OAAO,CAAC;AACnC,UAAM,UAAU,IAAI,KAAK,CAAC,KAAK,UAAU,MAAM,CAAC,GAAG;AAAA,MACjD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,UAAU,YAAY;AACxB,gBAAU;AAAA,QACR,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG;AAAA,QACrD;AAAA,MACF;AACA;AAAA,IACF;AAEA,SAAK,MAAM,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,MAAM;AAAA,MAC3B,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB;AACtB,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,YAAY,KAAK,IAAI,KAAQ,MAAO,KAAK,KAAK,YAAY;AAChE,SAAK,eAAe,KAAK,IAAI,KAAK,eAAe,GAAG,CAAC;AACrD,QAAI,KAAK,YAAY;AACnB,aAAO,aAAa,KAAK,UAAU;AAAA,IACrC;AACA,SAAK,aAAa,OAAO,WAAW,MAAM,KAAK,MAAM,GAAG,SAAS;AAAA,EACnE;AAAA,EAEQ,oBAA6B;AACnC,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,QAAI,KAAK,OAAO,KAAK,KAAK,OAAO,cAAc,GAAI,QAAO;AAC1D,QAAI,CAAC,KAAK,iBAAiB,EAAG,QAAO;AACrC,WAAO;AAAA,EACT;AAAA,EAEQ,mBAA4B;AAClC,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,UAAM,eAAe,KAAK,OAAO,sBAAsB;AACvD,QAAI,gBAAgB,EAAG,QAAO;AAE9B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,cAAc,MAAM;AAC1B,SAAK,kBAAkB,KAAK,gBAAgB;AAAA,MAC1C,CAAC,cAAc,YAAY;AAAA,IAC7B;AAEA,QAAI,KAAK,gBAAgB,UAAU,cAAc;AAC/C,aAAO;AAAA,IACT;AAEA,SAAK,gBAAgB,KAAK,GAAG;AAC7B,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa;AACnB,QAAI,OAAO,WAAW,eAAe,EAAE,WAAW,QAAS;AAE3D,UAAM,gBAAgB,OAAO,MAAM,KAAK,MAAM;AAC9C,WAAO,QAAQ,UAAU,SAAS;AAChC,YAAM,WAAW,MAAM,cAAc,GAAG,IAAI;AAE5C,UAAI;AACF,cAAM,UAAU,KAAK,CAAC;AACtB,cAAM,UACH,mBAAmB,UAChB,QAAQ,SACR,KAAK,CAAC,GAAG,WAAW;AAC1B,cAAM,MAAM,mBAAmB,UAAU,QAAQ,MAAM,OAAO,OAAO;AAErE,YAAI,CAAC,SAAS,IAAI;AAChB,eAAK,aAAa;AAAA,YAChB,MAAM;AAAA,YACN,SAAS,uBAAuB,SAAS,MAAM;AAAA,YAC/C,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,gBAAgB,SAAS;AAAA,YACzB,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,YAC5D,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,WAAW;AACjB,QAAI,OAAO,WAAW,eAAe,EAAE,oBAAoB,QAAS;AACpE,UAAM,MAAM;AACZ,UAAM,QAAQ,eAAe;AAK7B,QAAI,MAAM,YAAa;AACvB,UAAM,cAAc;AAEpB,UAAM,eAAe,MAAM;AAC3B,UAAM,eAAe,MAAM;AAE3B,UAAM,OAAO,SACX,QACA,KACA,OACA,MACA,UACA;AACA,YAAM,MAAM;AACZ,UAAI,WAAW,EAAE,QAAQ,KAAK,OAAO,GAAG,EAAE;AAC1C,aAAO,aAAa,KAAK,KAAK,QAAQ,KAAK,SAAS,MAAM,QAAQ,MAAM,YAAY,IAAI;AAAA,IAC1F;AAEA,UAAM,OAAO,SAAU,MAAiD;AACtE,YAAM,MAAM;AACZ,YAAM,OAAO,IAAI;AAEjB,YAAM,iBAAiB,MAAM;AAC3B,YAAI,CAAC,IAAI,UAAU,CAAC,KAAM;AAC1B,cAAM,SAAS,IAAI;AACnB,YAAI,UAAU,OAAO,WAAW,GAAG;AACjC,cAAI,aAAa;AAAA,YACf,MAAM;AAAA,YACN,SAAS,mBAAmB,UAAU,eAAe;AAAA,YACrD,WAAW;AAAA,YACX,YAAY,KAAK;AAAA,YACjB,eAAe,KAAK;AAAA,YACpB,gBAAgB,UAAU;AAAA,YAC1B,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,YAC5D,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,iBAAiB,WAAW,cAAc;AAC9C,UAAI,iBAAiB,SAAS,cAAc;AAE5C,aAAO,aAAa,KAAK,KAAK,QAAQ,IAAI;AAAA,IAC5C;AAAA,EACF;AAAA,EAEQ,kBAAkB;AACxB,QAAI,OAAO,WAAW,YAAa;AAEnC,UAAM,YAAY,QAAQ;AAC1B,UAAM,eAAe,QAAQ;AAE7B,UAAM,mBAAmB,MAAM;AAC7B,WAAK,aAAa;AAAA,QAChB,MAAM;AAAA,QACN,SAAS,iBAAiB,OAAO,SAAS,IAAI;AAAA,QAC9C,KAAK,OAAO,SAAS;AAAA,QACrB,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,YAAQ,YAAY,YAAa,MAAM;AACrC,YAAM,SAAS,UAAU,MAAM,MAAM,IAAa;AAClD,uBAAiB;AACjB,aAAO;AAAA,IACT;AAEA,YAAQ,eAAe,YAAa,MAAM;AACxC,YAAM,SAAS,aAAa,MAAM,MAAM,IAAa;AACrD,uBAAiB;AACjB,aAAO;AAAA,IACT;AAEA,WAAO,iBAAiB,YAAY,gBAAgB;AAAA,EACtD;AACF;AAEO,IAAM,UAAU,IAAI,WAAW;AAC/B,IAAM,OAAO,CAAC,WAA0B,QAAQ,KAAK,MAAM;AAC3D,IAAM,eAAe,CAAC,UAAmB,QAAQ,aAAa,KAAK;AACnE,IAAM,eAAe,CAAC,UAAoB,QAAQ,aAAa,KAAK;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent } from \"@vybesec/types\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vsPatched?: boolean;\n __vsMeta?: { method: string; url: string };\n };\n\n if (proto.__vsPatched) return;\n proto.__vsPatched = true;\n\n const originalOpen = proto.open;\n // narrow the send signature to match what we'll call\n const originalSend = proto.send as (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null\n ) => void;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vsMeta = { method, url: String(url) };\n return originalOpen.call(\n xhr,\n method,\n url,\n async ?? true,\n user ?? null,\n password ?? null\n );\n };\n\n // Accept any here and cast when calling the native send to avoid\n // TypeScript diagnostics around BodyInit / ReadableStream mismatch.\n proto.send = function (body?: any) {\n const xhr = this as typeof proto;\n const meta = xhr.__vsMeta;\n\n const handleComplete = () => {\n try {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } finally {\n // clean up listeners to avoid leaks / duplicate reporting\n xhr.removeEventListener(\"loadend\", handleComplete);\n xhr.removeEventListener(\"error\", handleComplete);\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n // Cast to the native expected type to satisfy the method signature.\n return originalSend.call(xhr, body as Document | XMLHttpRequestBodyInit | null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],"mappings":";;;;;AAqBA,IAAM,qBAAqB;AAC3B,IAAM,cAAc;AAEpB,SAAS,eAAuB;AAC9B,MAAI;AACF,UAAM,WAAW,OAAO,aAAa,QAAQ,WAAW;AACxD,QAAI,SAAU,QAAO;AACrB,UAAM,OAAO,OAAO,WAAW;AAC/B,WAAO,aAAa,QAAQ,aAAa,IAAI;AAC7C,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,OAAO,WAAW;AAAA,EAC3B;AACF;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,iBAAiB,MAAO,QAAO,MAAM,WAAW;AACpD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAwB;AAC5C,MAAI,iBAAiB,SAAS,MAAM,KAAM,QAAO,MAAM;AACvD,SAAO;AACT;AAEA,SAAS,cAAc,OAAoC;AACzD,MAAI,iBAAiB,MAAO,QAAO,MAAM;AACzC,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAoC;AAC9D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,SAAS;AACb,aAAW,WAAW,UAAU;AAC9B,aAAS,OAAO,QAAQ,SAAS,YAAY;AAAA,EAC/C;AACA,SAAO;AACT;AAEA,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AAExB,SAAS,WAAW,OAAgB,QAAQ,GAAY;AACtD,MAAI,SAAS,gBAAiB,QAAO;AACrC,MAAI,OAAO,UAAU,SAAU,QAAO,mBAAmB,KAAK,KAAK;AACnE,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,UAAU,WAAW,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC1D;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS;AACf,UAAM,OAAgC,CAAC;AACvC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,cAAc,KAAK,GAAG,GAAG;AAC3B,aAAK,GAAG,IAAI;AACZ;AAAA,MACF;AACA,WAAK,GAAG,IAAI,WAAW,OAAO,QAAQ,CAAC;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAA2B;AAC7C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,mBAAmB,MAAM,OAAO,KAAK,MAAM;AAAA,IACpD,YAAY,mBAAmB,MAAM,UAAU;AAAA,IAC/C,MAAM,MAAM,OAAQ,WAAW,MAAM,IAAI,IAA+B,MAAM;AAAA,IAC9E,OAAO,MAAM,QAAS,WAAW,MAAM,KAAK,IAAgC,MAAM;AAAA,EACpF;AACF;AAEO,IAAM,aAAN,MAAiB;AAAA,EAAjB;AACL,wBAAQ,UAA+B;AACvC,wBAAQ,UAAqB,CAAC;AAC9B,wBAAQ,mBAA4B,CAAC;AACrC,wBAAQ;AACR,wBAAQ;AACR,wBAAQ,gBAAe;AACvB,wBAAQ,cAAa;AAAA;AAAA,EAErB,KAAK,QAAuB;AAC1B,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,YAAY,OAAO,cAAc;AAAA,MACjC,WAAW,OAAO,aAAa;AAAA,MAC/B,oBAAoB,OAAO,sBAAsB;AAAA,MACjD,WAAW,OAAO,aAAa;AAAA,IACjC;AAEA,QAAI,OAAO,WAAW,YAAa;AAEnC,WAAO,iBAAiB,SAAS,CAAC,UAAU;AAC1C,WAAK,aAAa,MAAM,SAAS,MAAM,SAAS;AAAA,QAC9C,KAAK,MAAM;AAAA,MACb,CAAC;AAAA,IACH,CAAC;AAED,WAAO,iBAAiB,sBAAsB,CAAC,UAAU;AACvD,WAAK,aAAa,MAAM,MAAM;AAAA,IAChC,CAAC;AAED,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,gBAAgB;AAErB,WAAO,iBAAiB,oBAAoB,MAAM;AAChD,UAAI,SAAS,oBAAoB,UAAU;AACzC,aAAK,YAAY;AAAA,MACnB;AAAA,IACF,CAAC;AAED,QAAI,KAAK,YAAY;AACnB,aAAO,cAAc,KAAK,UAAU;AAAA,IACtC;AACA,QAAI,KAAK,YAAY;AACnB,aAAO,aAAa,KAAK,UAAU;AACnC,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,eAAe;AACpB,SAAK,aAAa,OAAO,YAAY,MAAM,KAAK,MAAM,GAAG,GAAI;AAAA,EAC/D;AAAA,EAEA,aAAa,OAAgB,SAAkC;AAC7D,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAE/B,UAAM,QAAkB,WAAW;AAAA,MACjC,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK;AAAA,MAC9B,YAAY,cAAc,KAAK;AAAA,MAC/B,WAAW,aAAa,KAAK;AAAA,MAC7B,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,MAC5D,WAAW,OAAO,WAAW,cAAc,aAAa,IAAI;AAAA,MAC5D,QAAQ,KAAK,OAAO;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,MACpB,MAAM;AAAA,QACJ,GAAI,WAAW,CAAC;AAAA,QAChB,UAAU,KAAK,OAAO,YAAY;AAAA,QAClC,aAAa,KAAK,OAAO,eAAe;AAAA,QACxC,SAAS,KAAK,OAAO,WAAW;AAAA,MAClC;AAAA,IACF,CAAC;AAED,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,aAAa,OAAiB;AAC5B,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAC/B,UAAM,WAAqB,WAAW;AAAA,MACpC,GAAG;AAAA,MACH,WAAW,MAAM,cAAc,OAAO,WAAW,cAAc,aAAa,IAAI;AAAA,MAChF,QAAQ,MAAM,UAAU,KAAK,OAAO;AAAA,MACpC,WAAW,MAAM,aAAa,KAAK,IAAI;AAAA,MACvC,MAAM;AAAA,QACJ,GAAI,MAAM,QAAQ,CAAC;AAAA,QACnB,UAAU,KAAK,OAAO,YAAY;AAAA,QAClC,aAAa,KAAK,OAAO,eAAe;AAAA,QACxC,SAAS,KAAK,OAAO,WAAW;AAAA,MAClC;AAAA,IACF,CAAC;AAED,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEQ,UAAU,OAAiB;AACjC,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,QAAI,aAAa,EAAG;AACpB,WAAO,KAAK,OAAO,UAAU,WAAW;AACtC,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,SAAK,OAAO,KAAK,KAAK;AACtB,QAAI,KAAK,OAAO,UAAU,IAAI;AAC5B,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ;AACpB,QAAI,CAAC,KAAK,UAAU,KAAK,WAAY;AACrC,QAAI,CAAC,KAAK,OAAO,OAAQ;AAEzB,SAAK,aAAa;AAClB,UAAM,SAAS,KAAK,OAAO,OAAO,CAAC;AAEnC,QAAI;AACF,YAAM,MAAM,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG,IAAI;AAAA,QACnE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,MAAM;AAAA,QAC3B,WAAW;AAAA,MACb,CAAC;AACD,WAAK,eAAe;AACpB,UAAI,KAAK,YAAY;AACnB,eAAO,aAAa,KAAK,UAAU;AACnC,aAAK,aAAa;AAAA,MACpB;AAAA,IACF,QAAQ;AACN,WAAK,OAAO,QAAQ,GAAG,MAAM;AAC7B,WAAK,cAAc;AAAA,IACrB,UAAE;AACA,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,cAAc;AACpB,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAO,OAAQ;AAEzC,UAAM,SAAS,KAAK,OAAO,OAAO,CAAC;AACnC,UAAM,UAAU,IAAI,KAAK,CAAC,KAAK,UAAU,MAAM,CAAC,GAAG;AAAA,MACjD,MAAM;AAAA,IACR,CAAC;AAED,QAAI,UAAU,YAAY;AACxB,gBAAU;AAAA,QACR,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG;AAAA,QACrD;AAAA,MACF;AACA;AAAA,IACF;AAEA,SAAK,MAAM,GAAG,KAAK,OAAO,SAAS,cAAc,KAAK,OAAO,GAAG,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,MAAM;AAAA,MAC3B,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB;AACtB,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,YAAY,KAAK,IAAI,KAAQ,MAAO,KAAK,KAAK,YAAY;AAChE,SAAK,eAAe,KAAK,IAAI,KAAK,eAAe,GAAG,CAAC;AACrD,QAAI,KAAK,YAAY;AACnB,aAAO,aAAa,KAAK,UAAU;AAAA,IACrC;AACA,SAAK,aAAa,OAAO,WAAW,MAAM,KAAK,MAAM,GAAG,SAAS;AAAA,EACnE;AAAA,EAEQ,oBAA6B;AACnC,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,QAAI,KAAK,OAAO,KAAK,KAAK,OAAO,cAAc,GAAI,QAAO;AAC1D,QAAI,CAAC,KAAK,iBAAiB,EAAG,QAAO;AACrC,WAAO;AAAA,EACT;AAAA,EAEQ,mBAA4B;AAClC,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,UAAM,eAAe,KAAK,OAAO,sBAAsB;AACvD,QAAI,gBAAgB,EAAG,QAAO;AAE9B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,cAAc,MAAM;AAC1B,SAAK,kBAAkB,KAAK,gBAAgB;AAAA,MAC1C,CAAC,cAAc,YAAY;AAAA,IAC7B;AAEA,QAAI,KAAK,gBAAgB,UAAU,cAAc;AAC/C,aAAO;AAAA,IACT;AAEA,SAAK,gBAAgB,KAAK,GAAG;AAC7B,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa;AACnB,QAAI,OAAO,WAAW,eAAe,EAAE,WAAW,QAAS;AAE3D,UAAM,gBAAgB,OAAO,MAAM,KAAK,MAAM;AAC9C,WAAO,QAAQ,UAAU,SAAS;AAChC,YAAM,WAAW,MAAM,cAAc,GAAG,IAAI;AAE5C,UAAI;AACF,cAAM,UAAU,KAAK,CAAC;AACtB,cAAM,UACH,mBAAmB,UAChB,QAAQ,SACR,KAAK,CAAC,GAAG,WAAW;AAC1B,cAAM,MAAM,mBAAmB,UAAU,QAAQ,MAAM,OAAO,OAAO;AAErE,YAAI,CAAC,SAAS,IAAI;AAChB,eAAK,aAAa;AAAA,YAChB,MAAM;AAAA,YACN,SAAS,uBAAuB,SAAS,MAAM;AAAA,YAC/C,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,gBAAgB,SAAS;AAAA,YACzB,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,YAC5D,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,WAAW;AACX,QAAI,OAAO,WAAW,eAAe,EAAE,oBAAoB,QAAS;AACpE,UAAM,MAAM;AACZ,UAAM,QAAQ,eAAe;AAK7B,QAAI,MAAM,YAAa;AACvB,UAAM,cAAc;AAEpB,UAAM,eAAe,MAAM;AAE3B,UAAM,eAAe,MAAM;AAK3B,UAAM,OAAO,SACX,QACA,KACA,OACA,MACA,UACA;AACA,YAAM,MAAM;AACZ,UAAI,WAAW,EAAE,QAAQ,KAAK,OAAO,GAAG,EAAE;AAC1C,aAAO,aAAa;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,IACF;AAIA,UAAM,OAAO,SAAU,MAAY;AACjC,YAAM,MAAM;AACZ,YAAM,OAAO,IAAI;AAEjB,YAAM,iBAAiB,MAAM;AAC3B,YAAI;AACF,cAAI,CAAC,IAAI,UAAU,CAAC,KAAM;AAC1B,gBAAM,SAAS,IAAI;AACnB,cAAI,UAAU,OAAO,WAAW,GAAG;AACjC,gBAAI,aAAa;AAAA,cACf,MAAM;AAAA,cACN,SAAS,mBAAmB,UAAU,eAAe;AAAA,cACrD,WAAW;AAAA,cACX,YAAY,KAAK;AAAA,cACjB,eAAe,KAAK;AAAA,cACpB,gBAAgB,UAAU;AAAA,cAC1B,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,cAC5D,WAAW,KAAK,IAAI;AAAA,YACtB,CAAC;AAAA,UACH;AAAA,QACF,UAAE;AAEA,cAAI,oBAAoB,WAAW,cAAc;AACjD,cAAI,oBAAoB,SAAS,cAAc;AAAA,QACjD;AAAA,MACF;AAEA,UAAI,iBAAiB,WAAW,cAAc;AAC9C,UAAI,iBAAiB,SAAS,cAAc;AAG5C,aAAO,aAAa,KAAK,KAAK,IAAgD;AAAA,IAChF;AAAA,EACF;AAAA,EAEE,kBAAkB;AACxB,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,YAAY,QAAQ;AAC1B,UAAM,eAAe,QAAQ;AAE7B,UAAM,mBAAmB,MAAM;AAC7B,WAAK,aAAa;AAAA,QAChB,MAAM;AAAA,QACN,SAAS,iBAAiB,OAAO,SAAS,IAAI;AAAA,QAC9C,KAAK,OAAO,SAAS;AAAA,QACrB,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,YAAQ,YAAY,YAAa,MAAM;AACrC,YAAM,SAAS,UAAU,MAAM,MAAM,IAAa;AAClD,uBAAiB;AACjB,aAAO;AAAA,IACT;AAEA,YAAQ,eAAe,YAAa,MAAM;AACxC,YAAM,SAAS,aAAa,MAAM,MAAM,IAAa;AACrD,uBAAiB;AACjB,aAAO;AAAA,IACT;AAEA,WAAO,iBAAiB,YAAY,gBAAgB;AAAA,EACtD;AACF;AAEO,IAAM,UAAU,IAAI,WAAW;AAC/B,IAAM,OAAO,CAAC,WAA0B,QAAQ,KAAK,MAAM;AAC3D,IAAM,eAAe,CAAC,UAAmB,QAAQ,aAAa,KAAK;AACnE,IAAM,eAAe,CAAC,UAAoB,QAAQ,aAAa,KAAK;","names":[]}
|
package/dist/v1/sdk.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var VybeSec=(()=>{var p=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var b=(t,e)=>{for(var n in e)p(t,n,{get:e[n],enumerable:!0})},R=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of E(e))!T.call(t,i)&&i!==n&&p(t,i,{get:()=>e[i],enumerable:!(r=v(e,i))||r.enumerable});return t};var k=t=>R(p({},"__esModule",{value:!0}),t);var
|
|
1
|
+
"use strict";var VybeSec=(()=>{var p=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var b=(t,e)=>{for(var n in e)p(t,n,{get:e[n],enumerable:!0})},R=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of E(e))!T.call(t,i)&&i!==n&&p(t,i,{get:()=>e[i],enumerable:!(r=v(e,i))||r.enumerable});return t};var k=t=>R(p({},"__esModule",{value:!0}),t);var q={};b(q,{VybeSecSDK:()=>h,captureError:()=>U,captureEvent:()=>D,init:()=>L,vybesec:()=>d});var S="https://vybesec-ingest.hexeldigitalstudio.workers.dev",g="vybesec_session_id";function w(){try{let t=window.localStorage.getItem(g);if(t)return t;let e=crypto.randomUUID();return window.localStorage.setItem(g,e),e}catch{return crypto.randomUUID()}}function x(t){if(t instanceof Error)return t.message||"Unknown error";if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return"Unknown error"}}function _(t){return t instanceof Error&&t.name?t.name:"Error"}function I(t){if(t instanceof Error)return t.stack}function l(t){if(!t)return t;let e=[/sk-[a-zA-Z0-9]{20,}/g,/pk_[a-zA-Z0-9]{20,}/g,/Bearer\s+[a-zA-Z0-9\-_.]{20,}/g,/password["']?\s*[:=]\s*["'][^"']+/gi],n=t;for(let r of e)n=n.replace(r,"[REDACTED]");return n}var M=/(password|token|secret|api[_-]?key|authorization)/i,A=3;function c(t,e=0){if(e>=A)return t;if(typeof t=="string")return l(t)??t;if(Array.isArray(t))return t.map(n=>c(n,e+1));if(t&&typeof t=="object"){let n=t,r={};for(let[i,s]of Object.entries(n)){if(M.test(i)){r[i]="[REDACTED]";continue}r[i]=c(s,e+1)}return r}return t}function y(t){return{...t,message:l(t.message)??t.message,stackTrace:l(t.stackTrace),tags:t.tags?c(t.tags):t.tags,extra:t.extra?c(t.extra):t.extra}}var h=class{config=null;buffer=[];eventTimestamps=[];flushTimer;retryTimer;retryAttempt=0;isFlushing=!1;init(e){this.config={...e,sampleRate:e.sampleRate??1,maxBuffer:e.maxBuffer??100,maxEventsPerMinute:e.maxEventsPerMinute??120,ingestUrl:e.ingestUrl??S},!(typeof window>"u")&&(window.addEventListener("error",n=>{this.captureError(n.error??n.message,{url:n.filename})}),window.addEventListener("unhandledrejection",n=>{this.captureError(n.reason)}),this.patchFetch(),this.patchXHR(),this.trackNavigation(),window.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.flushBeacon()}),this.flushTimer&&window.clearInterval(this.flushTimer),this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=void 0),this.retryAttempt=0,this.flushTimer=window.setInterval(()=>this.flush(),5e3))}captureError(e,n){if(!this.config||!this.shouldAcceptEvent())return;let r=y({type:"error",message:x(e),stackTrace:I(e),errorType:_(e),url:typeof window<"u"?window.location.href:void 0,sessionId:typeof window<"u"?w():void 0,userId:this.config.userId,timestamp:Date.now(),tags:{...n??{},platform:this.config.platform??"other",environment:this.config.environment??"production",release:this.config.release??""}});this.pushEvent(r)}captureEvent(e){if(!this.config||!this.shouldAcceptEvent())return;let n=y({...e,sessionId:e.sessionId??(typeof window<"u"?w():void 0),userId:e.userId??this.config.userId,timestamp:e.timestamp??Date.now(),tags:{...e.tags??{},platform:this.config.platform??"other",environment:this.config.environment??"production",release:this.config.release??""}});this.pushEvent(n)}pushEvent(e){if(!this.config)return;let n=this.config.maxBuffer??100;if(!(n<=0)){for(;this.buffer.length>=n;)this.buffer.shift();this.buffer.push(e),this.buffer.length>=10&&this.flush()}}async flush(){if(!this.config||this.isFlushing||!this.buffer.length)return;this.isFlushing=!0;let e=this.buffer.splice(0);try{await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0}),this.retryAttempt=0,this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=void 0)}catch{this.buffer.unshift(...e),this.scheduleRetry()}finally{this.isFlushing=!1}}flushBeacon(){if(!this.config||!this.buffer.length)return;let e=this.buffer.splice(0),n=new Blob([JSON.stringify(e)],{type:"application/json"});if(navigator.sendBeacon){navigator.sendBeacon(`${this.config.ingestUrl}/v1/events/${this.config.key}`,n);return}fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),keepalive:!0})}scheduleRetry(){if(typeof window>"u")return;let e=Math.min(3e4,1e3*2**this.retryAttempt);this.retryAttempt=Math.min(this.retryAttempt+1,5),this.retryTimer&&window.clearTimeout(this.retryTimer),this.retryTimer=window.setTimeout(()=>this.flush(),e)}shouldAcceptEvent(){return!(!this.config||Math.random()>(this.config.sampleRate??1)||!this.consumeRateLimit())}consumeRateLimit(){if(!this.config)return!1;let e=this.config.maxEventsPerMinute??120;if(e<=0)return!1;let n=Date.now(),r=n-6e4;return this.eventTimestamps=this.eventTimestamps.filter(i=>i>r),this.eventTimestamps.length>=e?!1:(this.eventTimestamps.push(n),!0)}patchFetch(){if(typeof window>"u"||!("fetch"in window))return;let e=window.fetch.bind(window);window.fetch=async(...n)=>{let r=await e(...n);try{let i=n[0],s=(i instanceof Request?i.method:n[1]?.method)??"GET",o=i instanceof Request?i.url:String(i);r.ok||this.captureEvent({type:"error",message:`Request failed with ${r.status}`,errorType:"HttpError",requestUrl:o,requestMethod:s,responseStatus:r.status,url:typeof window<"u"?window.location.href:void 0,timestamp:Date.now()})}catch{}return r}}patchXHR(){if(typeof window>"u"||!("XMLHttpRequest"in window))return;let e=this,n=XMLHttpRequest.prototype;if(n.__vsPatched)return;n.__vsPatched=!0;let r=n.open,i=n.send;n.open=function(s,o,f,a,u){let m=this;return m.__vsMeta={method:s,url:String(o)},r.call(m,s,o,f??!0,a??null,u??null)},n.send=function(s){let o=this,f=o.__vsMeta,a=()=>{try{if(!e.config||!f)return;let u=o.status;(u>=400||u===0)&&e.captureEvent({type:"error",message:`XHR failed with ${u||"network error"}`,errorType:"HttpError",requestUrl:f.url,requestMethod:f.method,responseStatus:u||void 0,url:typeof window<"u"?window.location.href:void 0,timestamp:Date.now()})}finally{o.removeEventListener("loadend",a),o.removeEventListener("error",a)}};return o.addEventListener("loadend",a),o.addEventListener("error",a),i.call(o,s)}}trackNavigation(){if(typeof window>"u")return;let e=history.pushState,n=history.replaceState,r=()=>{this.captureEvent({type:"info",message:`Navigation to ${window.location.href}`,url:window.location.href,timestamp:Date.now()})};history.pushState=function(...i){let s=e.apply(this,i);return r(),s},history.replaceState=function(...i){let s=n.apply(this,i);return r(),s},window.addEventListener("popstate",r)}},d=new h,L=t=>d.init(t),U=t=>d.captureError(t),D=t=>d.captureEvent(t);return k(q);})();
|
|
2
2
|
//# sourceMappingURL=sdk.js.map
|
package/dist/v1/sdk.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nexport type RawEvent = {\n type: \"error\" | \"warning\" | \"info\" | \"performance\" | \"custom\";\n message: string;\n stackTrace?: string;\n errorType?: string;\n url?: string;\n requestUrl?: string;\n requestMethod?: string;\n responseStatus?: number;\n sessionId?: string;\n userId?: string;\n timestamp: number;\n tags?: Record<string, string>;\n extra?: Record<string, unknown>;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vwPatched?: boolean;\n __vwMeta?: { method: string; url: string };\n };\n\n if (proto.__vwPatched) return;\n proto.__vwPatched = true;\n\n const originalOpen = proto.open;\n const originalSend = proto.send;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vwMeta = { method, url: String(url) };\n return originalOpen.call(xhr, method, url, async ?? true, user ?? null, password ?? null);\n };\n\n proto.send = function (body?: Document | XMLHttpRequestBodyInit | null) {\n const xhr = this as typeof proto;\n const meta = xhr.__vwMeta;\n\n const handleComplete = () => {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n return originalSend.call(xhr, body ?? null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],
|
|
5
|
-
"mappings": "2bAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,EAAA,iBAAAC,EAAA,iBAAAC,EAAA,SAAAC,EAAA,YAAAC,
|
|
4
|
+
"sourcesContent": ["import type { RawEvent } from \"@vybesec/types\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?:\n | \"lovable\"\n | \"cursor\"\n | \"replit\"\n | \"v0\"\n | \"bolt\"\n | \"windsurf\"\n | \"other\";\n release?: string;\n userId?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nconst DEFAULT_INGEST_URL = \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction getSessionId(): string {\n try {\n const existing = window.localStorage.getItem(SESSION_KEY);\n if (existing) return existing;\n const next = crypto.randomUUID();\n window.localStorage.setItem(SESSION_KEY, next);\n return next;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message || \"Unknown error\";\n if (typeof error === \"string\") return error;\n try {\n return JSON.stringify(error);\n } catch {\n return \"Unknown error\";\n }\n}\n\nfunction getErrorType(error: unknown): string {\n if (error instanceof Error && error.name) return error.name;\n return \"Error\";\n}\n\nfunction getStackTrace(error: unknown): string | undefined {\n if (error instanceof Error) return error.stack;\n return undefined;\n}\n\nfunction scrubSensitiveText(value?: string): string | undefined {\n if (!value) return value;\n const patterns = [\n /sk-[a-zA-Z0-9]{20,}/g,\n /pk_[a-zA-Z0-9]{20,}/g,\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/g,\n /password[\"']?\\s*[:=]\\s*[\"'][^\"']+/gi\n ];\n let output = value;\n for (const pattern of patterns) {\n output = output.replace(pattern, \"[REDACTED]\");\n }\n return output;\n}\n\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\n\nfunction scrubValue(value: unknown, depth = 0): unknown {\n if (depth >= MAX_SCRUB_DEPTH) return value;\n if (typeof value === \"string\") return scrubSensitiveText(value) ?? value;\n if (Array.isArray(value)) {\n return value.map((entry) => scrubValue(entry, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (SENSITIVE_KEY.test(key)) {\n next[key] = \"[REDACTED]\";\n continue;\n }\n next[key] = scrubValue(entry, depth + 1);\n }\n return next;\n }\n return value;\n}\n\nfunction scrubEvent(event: RawEvent): RawEvent {\n return {\n ...event,\n message: scrubSensitiveText(event.message) ?? event.message,\n stackTrace: scrubSensitiveText(event.stackTrace),\n tags: event.tags ? (scrubValue(event.tags) as Record<string, string>) : event.tags,\n extra: event.extra ? (scrubValue(event.extra) as Record<string, unknown>) : event.extra\n };\n}\n\nexport class VybeSecSDK {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: number;\n private retryTimer?: number;\n private retryAttempt = 0;\n private isFlushing = false;\n\n init(config: VybeSecConfig) {\n this.config = {\n ...config,\n sampleRate: config.sampleRate ?? 1,\n maxBuffer: config.maxBuffer ?? 100,\n maxEventsPerMinute: config.maxEventsPerMinute ?? 120,\n ingestUrl: config.ingestUrl ?? DEFAULT_INGEST_URL\n };\n\n if (typeof window === \"undefined\") return;\n\n window.addEventListener(\"error\", (event) => {\n this.captureError(event.error ?? event.message, {\n url: event.filename\n });\n });\n\n window.addEventListener(\"unhandledrejection\", (event) => {\n this.captureError(event.reason);\n });\n\n this.patchFetch();\n this.patchXHR();\n this.trackNavigation();\n\n window.addEventListener(\"visibilitychange\", () => {\n if (document.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n });\n\n if (this.flushTimer) {\n window.clearInterval(this.flushTimer);\n }\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n this.retryAttempt = 0;\n this.flushTimer = window.setInterval(() => this.flush(), 5000);\n }\n\n captureError(error: unknown, context?: Record<string, string>) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message: getErrorMessage(error),\n stackTrace: getStackTrace(error),\n errorType: getErrorType(error),\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n sessionId: typeof window !== \"undefined\" ? getSessionId() : undefined,\n userId: this.config.userId,\n timestamp: Date.now(),\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? (typeof window !== \"undefined\" ? getSessionId() : undefined),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"other\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n private pushEvent(event: RawEvent) {\n if (!this.config) return;\n const maxBuffer = this.config.maxBuffer ?? 100;\n if (maxBuffer <= 0) return;\n while (this.buffer.length >= maxBuffer) {\n this.buffer.shift();\n }\n this.buffer.push(event);\n if (this.buffer.length >= 10) {\n void this.flush();\n }\n }\n\n private async flush() {\n if (!this.config || this.isFlushing) return;\n if (!this.buffer.length) return;\n\n this.isFlushing = true;\n const events = this.buffer.splice(0);\n\n try {\n await fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n } catch {\n this.buffer.unshift(...events);\n this.scheduleRetry();\n } finally {\n this.isFlushing = false;\n }\n }\n\n private flushBeacon() {\n if (!this.config || !this.buffer.length) return;\n\n const events = this.buffer.splice(0);\n const payload = new Blob([JSON.stringify(events)], {\n type: \"application/json\"\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(\n `${this.config.ingestUrl}/v1/events/${this.config.key}`,\n payload\n );\n return;\n }\n\n void fetch(`${this.config.ingestUrl}/v1/events/${this.config.key}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(events),\n keepalive: true\n });\n }\n\n private scheduleRetry() {\n if (typeof window === \"undefined\") return;\n const backoffMs = Math.min(30_000, 1000 * 2 ** this.retryAttempt);\n this.retryAttempt = Math.min(this.retryAttempt + 1, 5);\n if (this.retryTimer) {\n window.clearTimeout(this.retryTimer);\n }\n this.retryTimer = window.setTimeout(() => this.flush(), backoffMs);\n }\n\n private shouldAcceptEvent(): boolean {\n if (!this.config) return false;\n if (Math.random() > (this.config.sampleRate ?? 1)) return false;\n if (!this.consumeRateLimit()) return false;\n return true;\n }\n\n private consumeRateLimit(): boolean {\n if (!this.config) return false;\n const maxPerMinute = this.config.maxEventsPerMinute ?? 120;\n if (maxPerMinute <= 0) return false;\n\n const now = Date.now();\n const windowStart = now - 60_000;\n this.eventTimestamps = this.eventTimestamps.filter(\n (timestamp) => timestamp > windowStart\n );\n\n if (this.eventTimestamps.length >= maxPerMinute) {\n return false;\n }\n\n this.eventTimestamps.push(now);\n return true;\n }\n\n private patchFetch() {\n if (typeof window === \"undefined\" || !(\"fetch\" in window)) return;\n\n const originalFetch = window.fetch.bind(window);\n window.fetch = async (...args) => {\n const response = await originalFetch(...args);\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request\n ? request.method\n : args[1]?.method) ?? \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (!response.ok) {\n this.captureEvent({\n type: \"error\",\n message: `Request failed with ${response.status}`,\n errorType: \"HttpError\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private patchXHR() {\n if (typeof window === \"undefined\" || !(\"XMLHttpRequest\" in window)) return;\n const sdk = this;\n const proto = XMLHttpRequest.prototype as XMLHttpRequest & {\n __vsPatched?: boolean;\n __vsMeta?: { method: string; url: string };\n };\n\n if (proto.__vsPatched) return;\n proto.__vsPatched = true;\n\n const originalOpen = proto.open;\n // narrow the send signature to match what we'll call\n const originalSend = proto.send as (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null\n ) => void;\n\n proto.open = function (\n method: string,\n url: string,\n async?: boolean,\n user?: string | null,\n password?: string | null\n ) {\n const xhr = this as typeof proto;\n xhr.__vsMeta = { method, url: String(url) };\n return originalOpen.call(\n xhr,\n method,\n url,\n async ?? true,\n user ?? null,\n password ?? null\n );\n };\n\n // Accept any here and cast when calling the native send to avoid\n // TypeScript diagnostics around BodyInit / ReadableStream mismatch.\n proto.send = function (body?: any) {\n const xhr = this as typeof proto;\n const meta = xhr.__vsMeta;\n\n const handleComplete = () => {\n try {\n if (!sdk.config || !meta) return;\n const status = xhr.status;\n if (status >= 400 || status === 0) {\n sdk.captureEvent({\n type: \"error\",\n message: `XHR failed with ${status || \"network error\"}`,\n errorType: \"HttpError\",\n requestUrl: meta.url,\n requestMethod: meta.method,\n responseStatus: status || undefined,\n url: typeof window !== \"undefined\" ? window.location.href : undefined,\n timestamp: Date.now()\n });\n }\n } finally {\n // clean up listeners to avoid leaks / duplicate reporting\n xhr.removeEventListener(\"loadend\", handleComplete);\n xhr.removeEventListener(\"error\", handleComplete);\n }\n };\n\n xhr.addEventListener(\"loadend\", handleComplete);\n xhr.addEventListener(\"error\", handleComplete);\n\n // Cast to the native expected type to satisfy the method signature.\n return originalSend.call(xhr, body as Document | XMLHttpRequestBodyInit | null);\n };\n }\n\n private trackNavigation() {\n if (typeof window === \"undefined\") return;\n const pushState = history.pushState;\n const replaceState = history.replaceState;\n\n const handleNavigation = () => {\n this.captureEvent({\n type: \"info\",\n message: `Navigation to ${window.location.href}`,\n url: window.location.href,\n timestamp: Date.now()\n });\n };\n\n history.pushState = function (...args) {\n const result = pushState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n history.replaceState = function (...args) {\n const result = replaceState.apply(this, args as never);\n handleNavigation();\n return result;\n };\n\n window.addEventListener(\"popstate\", handleNavigation);\n }\n}\n\nexport const vybesec = new VybeSecSDK();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["index_exports", "__export", "VybeSecSDK", "captureError", "captureEvent", "init", "vybesec", "DEFAULT_INGEST_URL", "SESSION_KEY", "getSessionId", "existing", "next", "getErrorMessage", "error", "getErrorType", "getStackTrace", "scrubSensitiveText", "value", "patterns", "output", "pattern", "SENSITIVE_KEY", "MAX_SCRUB_DEPTH", "scrubValue", "depth", "entry", "record", "key", "scrubEvent", "event", "config", "context", "enriched", "maxBuffer", "events", "payload", "backoffMs", "maxPerMinute", "now", "windowStart", "timestamp", "originalFetch", "args", "response", "request", "method", "url", "sdk", "proto", "originalOpen", "originalSend", "async", "user", "password", "xhr", "body", "meta", "handleComplete", "status", "pushState", "replaceState", "handleNavigation", "result"]
|
|
7
7
|
}
|