@vybesec/react-native 0.1.4 → 0.1.5
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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -174,7 +174,7 @@ var VybeSecRN = class {
|
|
|
174
174
|
sampleRate: config.sampleRate ?? 1,
|
|
175
175
|
maxBuffer: config.maxBuffer ?? 100,
|
|
176
176
|
maxEventsPerMinute: config.maxEventsPerMinute ?? 120,
|
|
177
|
-
ingestUrl:
|
|
177
|
+
ingestUrl: DEFAULT_INGEST_URL,
|
|
178
178
|
platform: config.platform ?? "react-native"
|
|
179
179
|
};
|
|
180
180
|
this.initSessionId();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent, Platform as VybeSecPlatform } from \"@vybesec/types\";\nimport AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport {\n DeviceEventEmitter,\n InteractionManager,\n Linking,\n Platform as RNPlatform\n} from \"react-native\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?: VybeSecPlatform;\n release?: string;\n appVersion?: string;\n userId?: string;\n deviceType?: \"mobile\" | \"tablet\" | \"desktop\";\n osName?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nconst DEFAULT_INGEST_URL =\n \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction generateId(): string {\n return `vs_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\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\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\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\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\nfunction detectSecuritySignal(message?: string, stack?: string): string | null {\n const combined = `${message ?? \"\"}\\n${stack ?? \"\"}`;\n if (/sk-[a-zA-Z0-9]{20,}/.test(combined)) return \"secret_key_exposed\";\n if (/pk_[a-zA-Z0-9]{20,}/.test(combined)) return \"public_key_exposed\";\n if (/Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(combined)) return \"bearer_token_exposed\";\n if (/api[_-]?key\\s*[:=]/i.test(combined)) return \"api_key_exposed\";\n return null;\n}\n\nfunction ratingFor(\n metric: string,\n value: number\n): \"good\" | \"needs_improvement\" | \"poor\" {\n const thresholds: Record<string, [number, number]> = {\n APP_START: [2000, 4000],\n SCREEN_RENDER: [1000, 2500],\n JS_FPS: [55, 30],\n SLOW_NETWORK: [3000, 7000]\n };\n const [good, poor] = thresholds[metric] ?? [0, 0];\n if (metric === \"JS_FPS\") {\n if (value >= good) return \"good\";\n if (value >= poor) return \"needs_improvement\";\n return \"poor\";\n }\n if (value <= good) return \"good\";\n if (value <= poor) return \"needs_improvement\";\n return \"poor\";\n}\n\nasync function setupPromiseRejectionTracking(\n onUnhandled: (error: unknown) => void\n) {\n try {\n const promiseImpl = await import(\"promise/setimmediate/es6-extensions\");\n const rejectionTracking = await import(\n \"promise/setimmediate/rejection-tracking\"\n );\n const PromiseImpl =\n (promiseImpl as unknown as { default?: PromiseConstructor }).default ??\n (promiseImpl as unknown as PromiseConstructor);\n if (PromiseImpl) {\n (globalThis as any).Promise = PromiseImpl;\n }\n const enable =\n (rejectionTracking as unknown as { enable?: Function }).enable ??\n (rejectionTracking as unknown as Function);\n if (typeof enable === \"function\") {\n enable({\n allRejections: true,\n onUnhandled: (_id: number, error: unknown) => onUnhandled(error)\n });\n }\n } catch {\n // ignore rejection tracking failures\n }\n}\n\nexport class VybeSecRN {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private retryTimer?: ReturnType<typeof setTimeout>;\n private retryAttempt = 0;\n private isFlushing = false;\n private sessionId?: string;\n private patchedStorage = false;\n private patchedFetch = false;\n private startTime = Date.now();\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 platform: config.platform ?? \"react-native\"\n };\n\n this.initSessionId();\n this.startTime = Date.now();\n\n this.installErrorHandler();\n void setupPromiseRejectionTracking((error) => this.captureError(error));\n this.patchFetch();\n this.patchAsyncStorage();\n this.attachDeepLinkListener();\n this.attachMemoryWarningListener();\n this.startPerfMonitors();\n\n if (this.flushTimer) clearInterval(this.flushTimer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryAttempt = 0;\n this.flushTimer = setInterval(() => void 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 message = getErrorMessage(error);\n const stackTrace = getStackTrace(error);\n const securitySignal = detectSecuritySignal(message, stackTrace);\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message,\n stackTrace,\n errorType: getErrorType(error),\n sessionId: this.sessionId ?? generateId(),\n userId: this.config.userId,\n timestamp: Date.now(),\n deviceType: this.config.deviceType ?? this.defaultDeviceType(),\n osName: this.config.osName ?? RNPlatform.OS,\n appVersion: this.config.appVersion ?? this.config.release,\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\",\n ...(securitySignal ? { securitySignal } : {})\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? this.sessionId ?? generateId(),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n deviceType: event.deviceType ?? this.config.deviceType ?? this.defaultDeviceType(),\n osName: event.osName ?? this.config.osName ?? RNPlatform.OS,\n appVersion: event.appVersion ?? this.config.appVersion ?? this.config.release,\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n trackScreenRender(screenName: string) {\n const startedAt = Date.now();\n return () => {\n const duration = Date.now() - startedAt;\n this.captureEvent({\n type: \"performance\",\n message: `Screen render ${screenName}`,\n timestamp: Date.now(),\n extra: {\n metricName: \"SCREEN_RENDER\",\n value: duration,\n rating: ratingFor(\"SCREEN_RENDER\", duration)\n },\n tags: { screen: screenName }\n });\n };\n }\n\n notifyMemoryWarning(details?: string) {\n this.captureEvent({\n type: \"performance\",\n message: \"Memory warning\",\n timestamp: Date.now(),\n extra: {\n metricName: \"MEMORY_WARNING\",\n value: 1,\n rating: \"needs_improvement\"\n },\n tags: details ? { details } : undefined\n });\n }\n\n private initSessionId() {\n const fallback = generateId();\n this.sessionId = fallback;\n AsyncStorage.getItem(SESSION_KEY)\n .then((stored: string | null) => {\n if (stored) {\n this.sessionId = stored;\n return;\n }\n return AsyncStorage.setItem(SESSION_KEY, fallback);\n })\n .catch(() => {\n // ignore storage failures\n });\n }\n\n private defaultDeviceType(): \"mobile\" | \"tablet\" {\n const isPad = (RNPlatform as { isPad?: boolean }).isPad;\n if (RNPlatform.OS === \"ios\" && isPad) return \"tablet\";\n return \"mobile\";\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 installErrorHandler() {\n const ErrorUtils = (globalThis as any).ErrorUtils;\n if (!ErrorUtils || typeof ErrorUtils.setGlobalHandler !== \"function\") {\n return;\n }\n const previous = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: unknown, isFatal: boolean) => {\n this.captureError(error, { isFatal: String(isFatal) });\n if (typeof previous === \"function\") {\n previous(error, isFatal);\n }\n });\n }\n\n private patchAsyncStorage() {\n if (this.patchedStorage) return;\n if (!AsyncStorage?.setItem) return;\n this.patchedStorage = true;\n const original = AsyncStorage.setItem.bind(\n AsyncStorage\n ) as unknown as (...args: any[]) => Promise<void>;\n AsyncStorage.setItem = async (key: string, value: string, ...rest: any[]) => {\n try {\n if (SENSITIVE_KEY.test(key)) {\n const looksSensitive =\n /sk-[a-zA-Z0-9]{20,}/.test(value) ||\n /pk_[a-zA-Z0-9]{20,}/.test(value) ||\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(value) ||\n /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\./.test(value);\n if (looksSensitive) {\n this.captureEvent({\n type: \"warning\",\n message: `Sensitive token stored in AsyncStorage (${key})`,\n timestamp: Date.now(),\n tags: { securitySignal: \"async_storage_token\" }\n });\n }\n }\n } catch {\n // ignore\n }\n void rest;\n return original(key, value);\n };\n }\n\n private patchFetch() {\n if (this.patchedFetch) return;\n if (typeof fetch !== \"function\") return;\n this.patchedFetch = true;\n\n const original = fetch.bind(globalThis) as (...args: any[]) => Promise<Response>;\n (globalThis as any).fetch = async (...args: any[]) => {\n const start = Date.now();\n const response = await original(...args);\n const duration = Date.now() - start;\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request ? request.method : args[1]?.method) ??\n \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (url.startsWith(\"http://\")) {\n this.captureEvent({\n type: \"warning\",\n message: \"Insecure HTTP request detected\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n tags: { securitySignal: \"insecure_http\" }\n });\n }\n\n if (duration > 3000) {\n this.captureEvent({\n type: \"performance\",\n message: \"Slow network call\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n extra: {\n metricName: \"SLOW_NETWORK\",\n value: duration,\n rating: ratingFor(\"SLOW_NETWORK\", duration)\n }\n });\n }\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 responseTimeMs: duration,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private attachDeepLinkListener() {\n try {\n Linking.addEventListener(\"url\", (event: { url: string }) => {\n const url = event?.url;\n if (!url) return;\n try {\n const parsed = new URL(url);\n const params: [string, string][] = [];\n parsed.searchParams.forEach((value, key) => {\n params.push([key, value]);\n });\n const sensitive = params.find(([key, value]: [string, string]) => {\n if (SENSITIVE_KEY.test(key)) return true;\n return /sk-[a-zA-Z0-9]{20,}|pk_[a-zA-Z0-9]{20,}|Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(\n value\n );\n });\n if (sensitive) {\n this.captureEvent({\n type: \"warning\",\n message: \"Sensitive data detected in deep link\",\n timestamp: Date.now(),\n tags: { securitySignal: \"deep_link_leak\" },\n extra: { url }\n });\n }\n } catch {\n // ignore\n }\n });\n } catch {\n // ignore linking errors\n }\n }\n\n private attachMemoryWarningListener() {\n try {\n DeviceEventEmitter.addListener(\"memoryWarning\", () => {\n this.notifyMemoryWarning();\n });\n } catch {\n // ignore\n }\n }\n\n private startPerfMonitors() {\n InteractionManager.runAfterInteractions(() => {\n const duration = Date.now() - this.startTime;\n this.captureEvent({\n type: \"performance\",\n message: \"App start\",\n timestamp: Date.now(),\n extra: {\n metricName: \"APP_START\",\n value: duration,\n rating: ratingFor(\"APP_START\", duration)\n }\n });\n });\n\n const sampleFps = () => {\n const start = Date.now();\n let frames = 0;\n const loop = () => {\n frames += 1;\n if (Date.now() - start < 1000) {\n requestAnimationFrame(loop);\n } else {\n const fps = frames;\n this.captureEvent({\n type: \"performance\",\n message: \"JS thread FPS\",\n timestamp: Date.now(),\n extra: {\n metricName: \"JS_FPS\",\n value: fps,\n rating: ratingFor(\"JS_FPS\", fps)\n }\n });\n }\n };\n requestAnimationFrame(loop);\n };\n\n sampleFps();\n setInterval(sampleFps, 30_000);\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 });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n 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 scheduleRetry() {\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 clearTimeout(this.retryTimer);\n }\n this.retryTimer = setTimeout(() => void 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\nexport const vybesec = new VybeSecRN();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\nexport const trackScreenRender = (screenName: string) =>\n vybesec.trackScreenRender(screenName);\nexport const notifyMemoryWarning = (details?: string) =>\n vybesec.notifyMemoryWarning(details);\n"],"mappings":"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","names":["RNPlatform","AsyncStorage"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent, Platform as VybeSecPlatform } from \"@vybesec/types\";\nimport AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport {\n DeviceEventEmitter,\n InteractionManager,\n Linking,\n Platform as RNPlatform\n} from \"react-native\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?: VybeSecPlatform;\n release?: string;\n appVersion?: string;\n userId?: string;\n deviceType?: \"mobile\" | \"tablet\" | \"desktop\";\n osName?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n};\n\ntype InternalConfig = VybeSecConfig & {\n ingestUrl: string;\n};\n\nconst DEFAULT_INGEST_URL =\n \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction generateId(): string {\n return `vs_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\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\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\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\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\nfunction detectSecuritySignal(message?: string, stack?: string): string | null {\n const combined = `${message ?? \"\"}\\n${stack ?? \"\"}`;\n if (/sk-[a-zA-Z0-9]{20,}/.test(combined)) return \"secret_key_exposed\";\n if (/pk_[a-zA-Z0-9]{20,}/.test(combined)) return \"public_key_exposed\";\n if (/Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(combined)) return \"bearer_token_exposed\";\n if (/api[_-]?key\\s*[:=]/i.test(combined)) return \"api_key_exposed\";\n return null;\n}\n\nfunction ratingFor(\n metric: string,\n value: number\n): \"good\" | \"needs_improvement\" | \"poor\" {\n const thresholds: Record<string, [number, number]> = {\n APP_START: [2000, 4000],\n SCREEN_RENDER: [1000, 2500],\n JS_FPS: [55, 30],\n SLOW_NETWORK: [3000, 7000]\n };\n const [good, poor] = thresholds[metric] ?? [0, 0];\n if (metric === \"JS_FPS\") {\n if (value >= good) return \"good\";\n if (value >= poor) return \"needs_improvement\";\n return \"poor\";\n }\n if (value <= good) return \"good\";\n if (value <= poor) return \"needs_improvement\";\n return \"poor\";\n}\n\nasync function setupPromiseRejectionTracking(\n onUnhandled: (error: unknown) => void\n) {\n try {\n const promiseImpl = await import(\"promise/setimmediate/es6-extensions\");\n const rejectionTracking = await import(\n \"promise/setimmediate/rejection-tracking\"\n );\n const PromiseImpl =\n (promiseImpl as unknown as { default?: PromiseConstructor }).default ??\n (promiseImpl as unknown as PromiseConstructor);\n if (PromiseImpl) {\n (globalThis as any).Promise = PromiseImpl;\n }\n const enable =\n (rejectionTracking as unknown as { enable?: Function }).enable ??\n (rejectionTracking as unknown as Function);\n if (typeof enable === \"function\") {\n enable({\n allRejections: true,\n onUnhandled: (_id: number, error: unknown) => onUnhandled(error)\n });\n }\n } catch {\n // ignore rejection tracking failures\n }\n}\n\nexport class VybeSecRN {\n private config: InternalConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private retryTimer?: ReturnType<typeof setTimeout>;\n private retryAttempt = 0;\n private isFlushing = false;\n private sessionId?: string;\n private patchedStorage = false;\n private patchedFetch = false;\n private startTime = Date.now();\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: DEFAULT_INGEST_URL,\n platform: config.platform ?? \"react-native\"\n };\n\n this.initSessionId();\n this.startTime = Date.now();\n\n this.installErrorHandler();\n void setupPromiseRejectionTracking((error) => this.captureError(error));\n this.patchFetch();\n this.patchAsyncStorage();\n this.attachDeepLinkListener();\n this.attachMemoryWarningListener();\n this.startPerfMonitors();\n\n if (this.flushTimer) clearInterval(this.flushTimer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryAttempt = 0;\n this.flushTimer = setInterval(() => void 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 message = getErrorMessage(error);\n const stackTrace = getStackTrace(error);\n const securitySignal = detectSecuritySignal(message, stackTrace);\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message,\n stackTrace,\n errorType: getErrorType(error),\n sessionId: this.sessionId ?? generateId(),\n userId: this.config.userId,\n timestamp: Date.now(),\n deviceType: this.config.deviceType ?? this.defaultDeviceType(),\n osName: this.config.osName ?? RNPlatform.OS,\n appVersion: this.config.appVersion ?? this.config.release,\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\",\n ...(securitySignal ? { securitySignal } : {})\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? this.sessionId ?? generateId(),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n deviceType: event.deviceType ?? this.config.deviceType ?? this.defaultDeviceType(),\n osName: event.osName ?? this.config.osName ?? RNPlatform.OS,\n appVersion: event.appVersion ?? this.config.appVersion ?? this.config.release,\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n trackScreenRender(screenName: string) {\n const startedAt = Date.now();\n return () => {\n const duration = Date.now() - startedAt;\n this.captureEvent({\n type: \"performance\",\n message: `Screen render ${screenName}`,\n timestamp: Date.now(),\n extra: {\n metricName: \"SCREEN_RENDER\",\n value: duration,\n rating: ratingFor(\"SCREEN_RENDER\", duration)\n },\n tags: { screen: screenName }\n });\n };\n }\n\n notifyMemoryWarning(details?: string) {\n this.captureEvent({\n type: \"performance\",\n message: \"Memory warning\",\n timestamp: Date.now(),\n extra: {\n metricName: \"MEMORY_WARNING\",\n value: 1,\n rating: \"needs_improvement\"\n },\n tags: details ? { details } : undefined\n });\n }\n\n private initSessionId() {\n const fallback = generateId();\n this.sessionId = fallback;\n AsyncStorage.getItem(SESSION_KEY)\n .then((stored: string | null) => {\n if (stored) {\n this.sessionId = stored;\n return;\n }\n return AsyncStorage.setItem(SESSION_KEY, fallback);\n })\n .catch(() => {\n // ignore storage failures\n });\n }\n\n private defaultDeviceType(): \"mobile\" | \"tablet\" {\n const isPad = (RNPlatform as { isPad?: boolean }).isPad;\n if (RNPlatform.OS === \"ios\" && isPad) return \"tablet\";\n return \"mobile\";\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 installErrorHandler() {\n const ErrorUtils = (globalThis as any).ErrorUtils;\n if (!ErrorUtils || typeof ErrorUtils.setGlobalHandler !== \"function\") {\n return;\n }\n const previous = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: unknown, isFatal: boolean) => {\n this.captureError(error, { isFatal: String(isFatal) });\n if (typeof previous === \"function\") {\n previous(error, isFatal);\n }\n });\n }\n\n private patchAsyncStorage() {\n if (this.patchedStorage) return;\n if (!AsyncStorage?.setItem) return;\n this.patchedStorage = true;\n const original = AsyncStorage.setItem.bind(\n AsyncStorage\n ) as unknown as (...args: any[]) => Promise<void>;\n AsyncStorage.setItem = async (key: string, value: string, ...rest: any[]) => {\n try {\n if (SENSITIVE_KEY.test(key)) {\n const looksSensitive =\n /sk-[a-zA-Z0-9]{20,}/.test(value) ||\n /pk_[a-zA-Z0-9]{20,}/.test(value) ||\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(value) ||\n /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\./.test(value);\n if (looksSensitive) {\n this.captureEvent({\n type: \"warning\",\n message: `Sensitive token stored in AsyncStorage (${key})`,\n timestamp: Date.now(),\n tags: { securitySignal: \"async_storage_token\" }\n });\n }\n }\n } catch {\n // ignore\n }\n void rest;\n return original(key, value);\n };\n }\n\n private patchFetch() {\n if (this.patchedFetch) return;\n if (typeof fetch !== \"function\") return;\n this.patchedFetch = true;\n\n const original = fetch.bind(globalThis) as (...args: any[]) => Promise<Response>;\n (globalThis as any).fetch = async (...args: any[]) => {\n const start = Date.now();\n const response = await original(...args);\n const duration = Date.now() - start;\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request ? request.method : args[1]?.method) ??\n \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (url.startsWith(\"http://\")) {\n this.captureEvent({\n type: \"warning\",\n message: \"Insecure HTTP request detected\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n tags: { securitySignal: \"insecure_http\" }\n });\n }\n\n if (duration > 3000) {\n this.captureEvent({\n type: \"performance\",\n message: \"Slow network call\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n extra: {\n metricName: \"SLOW_NETWORK\",\n value: duration,\n rating: ratingFor(\"SLOW_NETWORK\", duration)\n }\n });\n }\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 responseTimeMs: duration,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private attachDeepLinkListener() {\n try {\n Linking.addEventListener(\"url\", (event: { url: string }) => {\n const url = event?.url;\n if (!url) return;\n try {\n const parsed = new URL(url);\n const params: [string, string][] = [];\n parsed.searchParams.forEach((value, key) => {\n params.push([key, value]);\n });\n const sensitive = params.find(([key, value]: [string, string]) => {\n if (SENSITIVE_KEY.test(key)) return true;\n return /sk-[a-zA-Z0-9]{20,}|pk_[a-zA-Z0-9]{20,}|Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(\n value\n );\n });\n if (sensitive) {\n this.captureEvent({\n type: \"warning\",\n message: \"Sensitive data detected in deep link\",\n timestamp: Date.now(),\n tags: { securitySignal: \"deep_link_leak\" },\n extra: { url }\n });\n }\n } catch {\n // ignore\n }\n });\n } catch {\n // ignore linking errors\n }\n }\n\n private attachMemoryWarningListener() {\n try {\n DeviceEventEmitter.addListener(\"memoryWarning\", () => {\n this.notifyMemoryWarning();\n });\n } catch {\n // ignore\n }\n }\n\n private startPerfMonitors() {\n InteractionManager.runAfterInteractions(() => {\n const duration = Date.now() - this.startTime;\n this.captureEvent({\n type: \"performance\",\n message: \"App start\",\n timestamp: Date.now(),\n extra: {\n metricName: \"APP_START\",\n value: duration,\n rating: ratingFor(\"APP_START\", duration)\n }\n });\n });\n\n const sampleFps = () => {\n const start = Date.now();\n let frames = 0;\n const loop = () => {\n frames += 1;\n if (Date.now() - start < 1000) {\n requestAnimationFrame(loop);\n } else {\n const fps = frames;\n this.captureEvent({\n type: \"performance\",\n message: \"JS thread FPS\",\n timestamp: Date.now(),\n extra: {\n metricName: \"JS_FPS\",\n value: fps,\n rating: ratingFor(\"JS_FPS\", fps)\n }\n });\n }\n };\n requestAnimationFrame(loop);\n };\n\n sampleFps();\n setInterval(sampleFps, 30_000);\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 });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n 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 scheduleRetry() {\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 clearTimeout(this.retryTimer);\n }\n this.retryTimer = setTimeout(() => void 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\nexport const vybesec = new VybeSecRN();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\nexport const trackScreenRender = (screenName: string) =>\n vybesec.trackScreenRender(screenName);\nexport const notifyMemoryWarning = (details?: string) =>\n vybesec.notifyMemoryWarning(details);\n"],"mappings":"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","names":["RNPlatform","AsyncStorage"]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -141,7 +141,7 @@ var VybeSecRN = class {
|
|
|
141
141
|
sampleRate: config.sampleRate ?? 1,
|
|
142
142
|
maxBuffer: config.maxBuffer ?? 100,
|
|
143
143
|
maxEventsPerMinute: config.maxEventsPerMinute ?? 120,
|
|
144
|
-
ingestUrl:
|
|
144
|
+
ingestUrl: DEFAULT_INGEST_URL,
|
|
145
145
|
platform: config.platform ?? "react-native"
|
|
146
146
|
};
|
|
147
147
|
this.initSessionId();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent, Platform as VybeSecPlatform } from \"@vybesec/types\";\nimport AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport {\n DeviceEventEmitter,\n InteractionManager,\n Linking,\n Platform as RNPlatform\n} from \"react-native\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?: VybeSecPlatform;\n release?: string;\n appVersion?: string;\n userId?: string;\n deviceType?: \"mobile\" | \"tablet\" | \"desktop\";\n osName?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n ingestUrl?: string;\n};\n\nconst DEFAULT_INGEST_URL =\n \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction generateId(): string {\n return `vs_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\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\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\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\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\nfunction detectSecuritySignal(message?: string, stack?: string): string | null {\n const combined = `${message ?? \"\"}\\n${stack ?? \"\"}`;\n if (/sk-[a-zA-Z0-9]{20,}/.test(combined)) return \"secret_key_exposed\";\n if (/pk_[a-zA-Z0-9]{20,}/.test(combined)) return \"public_key_exposed\";\n if (/Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(combined)) return \"bearer_token_exposed\";\n if (/api[_-]?key\\s*[:=]/i.test(combined)) return \"api_key_exposed\";\n return null;\n}\n\nfunction ratingFor(\n metric: string,\n value: number\n): \"good\" | \"needs_improvement\" | \"poor\" {\n const thresholds: Record<string, [number, number]> = {\n APP_START: [2000, 4000],\n SCREEN_RENDER: [1000, 2500],\n JS_FPS: [55, 30],\n SLOW_NETWORK: [3000, 7000]\n };\n const [good, poor] = thresholds[metric] ?? [0, 0];\n if (metric === \"JS_FPS\") {\n if (value >= good) return \"good\";\n if (value >= poor) return \"needs_improvement\";\n return \"poor\";\n }\n if (value <= good) return \"good\";\n if (value <= poor) return \"needs_improvement\";\n return \"poor\";\n}\n\nasync function setupPromiseRejectionTracking(\n onUnhandled: (error: unknown) => void\n) {\n try {\n const promiseImpl = await import(\"promise/setimmediate/es6-extensions\");\n const rejectionTracking = await import(\n \"promise/setimmediate/rejection-tracking\"\n );\n const PromiseImpl =\n (promiseImpl as unknown as { default?: PromiseConstructor }).default ??\n (promiseImpl as unknown as PromiseConstructor);\n if (PromiseImpl) {\n (globalThis as any).Promise = PromiseImpl;\n }\n const enable =\n (rejectionTracking as unknown as { enable?: Function }).enable ??\n (rejectionTracking as unknown as Function);\n if (typeof enable === \"function\") {\n enable({\n allRejections: true,\n onUnhandled: (_id: number, error: unknown) => onUnhandled(error)\n });\n }\n } catch {\n // ignore rejection tracking failures\n }\n}\n\nexport class VybeSecRN {\n private config: VybeSecConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private retryTimer?: ReturnType<typeof setTimeout>;\n private retryAttempt = 0;\n private isFlushing = false;\n private sessionId?: string;\n private patchedStorage = false;\n private patchedFetch = false;\n private startTime = Date.now();\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 platform: config.platform ?? \"react-native\"\n };\n\n this.initSessionId();\n this.startTime = Date.now();\n\n this.installErrorHandler();\n void setupPromiseRejectionTracking((error) => this.captureError(error));\n this.patchFetch();\n this.patchAsyncStorage();\n this.attachDeepLinkListener();\n this.attachMemoryWarningListener();\n this.startPerfMonitors();\n\n if (this.flushTimer) clearInterval(this.flushTimer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryAttempt = 0;\n this.flushTimer = setInterval(() => void 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 message = getErrorMessage(error);\n const stackTrace = getStackTrace(error);\n const securitySignal = detectSecuritySignal(message, stackTrace);\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message,\n stackTrace,\n errorType: getErrorType(error),\n sessionId: this.sessionId ?? generateId(),\n userId: this.config.userId,\n timestamp: Date.now(),\n deviceType: this.config.deviceType ?? this.defaultDeviceType(),\n osName: this.config.osName ?? RNPlatform.OS,\n appVersion: this.config.appVersion ?? this.config.release,\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\",\n ...(securitySignal ? { securitySignal } : {})\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? this.sessionId ?? generateId(),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n deviceType: event.deviceType ?? this.config.deviceType ?? this.defaultDeviceType(),\n osName: event.osName ?? this.config.osName ?? RNPlatform.OS,\n appVersion: event.appVersion ?? this.config.appVersion ?? this.config.release,\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n trackScreenRender(screenName: string) {\n const startedAt = Date.now();\n return () => {\n const duration = Date.now() - startedAt;\n this.captureEvent({\n type: \"performance\",\n message: `Screen render ${screenName}`,\n timestamp: Date.now(),\n extra: {\n metricName: \"SCREEN_RENDER\",\n value: duration,\n rating: ratingFor(\"SCREEN_RENDER\", duration)\n },\n tags: { screen: screenName }\n });\n };\n }\n\n notifyMemoryWarning(details?: string) {\n this.captureEvent({\n type: \"performance\",\n message: \"Memory warning\",\n timestamp: Date.now(),\n extra: {\n metricName: \"MEMORY_WARNING\",\n value: 1,\n rating: \"needs_improvement\"\n },\n tags: details ? { details } : undefined\n });\n }\n\n private initSessionId() {\n const fallback = generateId();\n this.sessionId = fallback;\n AsyncStorage.getItem(SESSION_KEY)\n .then((stored: string | null) => {\n if (stored) {\n this.sessionId = stored;\n return;\n }\n return AsyncStorage.setItem(SESSION_KEY, fallback);\n })\n .catch(() => {\n // ignore storage failures\n });\n }\n\n private defaultDeviceType(): \"mobile\" | \"tablet\" {\n const isPad = (RNPlatform as { isPad?: boolean }).isPad;\n if (RNPlatform.OS === \"ios\" && isPad) return \"tablet\";\n return \"mobile\";\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 installErrorHandler() {\n const ErrorUtils = (globalThis as any).ErrorUtils;\n if (!ErrorUtils || typeof ErrorUtils.setGlobalHandler !== \"function\") {\n return;\n }\n const previous = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: unknown, isFatal: boolean) => {\n this.captureError(error, { isFatal: String(isFatal) });\n if (typeof previous === \"function\") {\n previous(error, isFatal);\n }\n });\n }\n\n private patchAsyncStorage() {\n if (this.patchedStorage) return;\n if (!AsyncStorage?.setItem) return;\n this.patchedStorage = true;\n const original = AsyncStorage.setItem.bind(\n AsyncStorage\n ) as unknown as (...args: any[]) => Promise<void>;\n AsyncStorage.setItem = async (key: string, value: string, ...rest: any[]) => {\n try {\n if (SENSITIVE_KEY.test(key)) {\n const looksSensitive =\n /sk-[a-zA-Z0-9]{20,}/.test(value) ||\n /pk_[a-zA-Z0-9]{20,}/.test(value) ||\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(value) ||\n /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\./.test(value);\n if (looksSensitive) {\n this.captureEvent({\n type: \"warning\",\n message: `Sensitive token stored in AsyncStorage (${key})`,\n timestamp: Date.now(),\n tags: { securitySignal: \"async_storage_token\" }\n });\n }\n }\n } catch {\n // ignore\n }\n void rest;\n return original(key, value);\n };\n }\n\n private patchFetch() {\n if (this.patchedFetch) return;\n if (typeof fetch !== \"function\") return;\n this.patchedFetch = true;\n\n const original = fetch.bind(globalThis) as (...args: any[]) => Promise<Response>;\n (globalThis as any).fetch = async (...args: any[]) => {\n const start = Date.now();\n const response = await original(...args);\n const duration = Date.now() - start;\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request ? request.method : args[1]?.method) ??\n \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (url.startsWith(\"http://\")) {\n this.captureEvent({\n type: \"warning\",\n message: \"Insecure HTTP request detected\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n tags: { securitySignal: \"insecure_http\" }\n });\n }\n\n if (duration > 3000) {\n this.captureEvent({\n type: \"performance\",\n message: \"Slow network call\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n extra: {\n metricName: \"SLOW_NETWORK\",\n value: duration,\n rating: ratingFor(\"SLOW_NETWORK\", duration)\n }\n });\n }\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 responseTimeMs: duration,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private attachDeepLinkListener() {\n try {\n Linking.addEventListener(\"url\", (event: { url: string }) => {\n const url = event?.url;\n if (!url) return;\n try {\n const parsed = new URL(url);\n const params: [string, string][] = [];\n parsed.searchParams.forEach((value, key) => {\n params.push([key, value]);\n });\n const sensitive = params.find(([key, value]: [string, string]) => {\n if (SENSITIVE_KEY.test(key)) return true;\n return /sk-[a-zA-Z0-9]{20,}|pk_[a-zA-Z0-9]{20,}|Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(\n value\n );\n });\n if (sensitive) {\n this.captureEvent({\n type: \"warning\",\n message: \"Sensitive data detected in deep link\",\n timestamp: Date.now(),\n tags: { securitySignal: \"deep_link_leak\" },\n extra: { url }\n });\n }\n } catch {\n // ignore\n }\n });\n } catch {\n // ignore linking errors\n }\n }\n\n private attachMemoryWarningListener() {\n try {\n DeviceEventEmitter.addListener(\"memoryWarning\", () => {\n this.notifyMemoryWarning();\n });\n } catch {\n // ignore\n }\n }\n\n private startPerfMonitors() {\n InteractionManager.runAfterInteractions(() => {\n const duration = Date.now() - this.startTime;\n this.captureEvent({\n type: \"performance\",\n message: \"App start\",\n timestamp: Date.now(),\n extra: {\n metricName: \"APP_START\",\n value: duration,\n rating: ratingFor(\"APP_START\", duration)\n }\n });\n });\n\n const sampleFps = () => {\n const start = Date.now();\n let frames = 0;\n const loop = () => {\n frames += 1;\n if (Date.now() - start < 1000) {\n requestAnimationFrame(loop);\n } else {\n const fps = frames;\n this.captureEvent({\n type: \"performance\",\n message: \"JS thread FPS\",\n timestamp: Date.now(),\n extra: {\n metricName: \"JS_FPS\",\n value: fps,\n rating: ratingFor(\"JS_FPS\", fps)\n }\n });\n }\n };\n requestAnimationFrame(loop);\n };\n\n sampleFps();\n setInterval(sampleFps, 30_000);\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 });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n 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 scheduleRetry() {\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 clearTimeout(this.retryTimer);\n }\n this.retryTimer = setTimeout(() => void 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\nexport const vybesec = new VybeSecRN();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\nexport const trackScreenRender = (screenName: string) =>\n vybesec.trackScreenRender(screenName);\nexport const notifyMemoryWarning = (details?: string) =>\n vybesec.notifyMemoryWarning(details);\n"],"mappings":";;;;;AACA,OAAO,kBAAkB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,OACP;AAiBP,IAAM,qBACJ;AACF,IAAM,cAAc;AAEpB,SAAS,aAAqB;AAC5B,SAAO,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAC5E;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,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AAExB,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,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;AAEA,SAAS,qBAAqB,SAAkB,OAA+B;AAC7E,QAAM,WAAW,GAAG,WAAW,EAAE;AAAA,EAAK,SAAS,EAAE;AACjD,MAAI,sBAAsB,KAAK,QAAQ,EAAG,QAAO;AACjD,MAAI,sBAAsB,KAAK,QAAQ,EAAG,QAAO;AACjD,MAAI,gCAAgC,KAAK,QAAQ,EAAG,QAAO;AAC3D,MAAI,sBAAsB,KAAK,QAAQ,EAAG,QAAO;AACjD,SAAO;AACT;AAEA,SAAS,UACP,QACA,OACuC;AACvC,QAAM,aAA+C;AAAA,IACnD,WAAW,CAAC,KAAM,GAAI;AAAA,IACtB,eAAe,CAAC,KAAM,IAAI;AAAA,IAC1B,QAAQ,CAAC,IAAI,EAAE;AAAA,IACf,cAAc,CAAC,KAAM,GAAI;AAAA,EAC3B;AACA,QAAM,CAAC,MAAM,IAAI,IAAI,WAAW,MAAM,KAAK,CAAC,GAAG,CAAC;AAChD,MAAI,WAAW,UAAU;AACvB,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI,SAAS,KAAM,QAAO;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,KAAM,QAAO;AAC1B,SAAO;AACT;AAEA,eAAe,8BACb,aACA;AACA,MAAI;AACF,UAAM,cAAc,MAAM,OAAO,qCAAqC;AACtE,UAAM,oBAAoB,MAAM,OAC9B,yCACF;AACA,UAAM,cACH,YAA4D,WAC5D;AACH,QAAI,aAAa;AACf,MAAC,WAAmB,UAAU;AAAA,IAChC;AACA,UAAM,SACH,kBAAuD,UACvD;AACH,QAAI,OAAO,WAAW,YAAY;AAChC,aAAO;AAAA,QACL,eAAe;AAAA,QACf,aAAa,CAAC,KAAa,UAAmB,YAAY,KAAK;AAAA,MACjE,CAAC;AAAA,IACH;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,IAAM,YAAN,MAAgB;AAAA,EAAhB;AACL,wBAAQ,UAA+B;AACvC,wBAAQ,UAAqB,CAAC;AAC9B,wBAAQ,mBAA4B,CAAC;AACrC,wBAAQ;AACR,wBAAQ;AACR,wBAAQ,gBAAe;AACvB,wBAAQ,cAAa;AACrB,wBAAQ;AACR,wBAAQ,kBAAiB;AACzB,wBAAQ,gBAAe;AACvB,wBAAQ,aAAY,KAAK,IAAI;AAAA;AAAA,EAE7B,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,MAC/B,UAAU,OAAO,YAAY;AAAA,IAC/B;AAEA,SAAK,cAAc;AACnB,SAAK,YAAY,KAAK,IAAI;AAE1B,SAAK,oBAAoB;AACzB,SAAK,8BAA8B,CAAC,UAAU,KAAK,aAAa,KAAK,CAAC;AACtE,SAAK,WAAW;AAChB,SAAK,kBAAkB;AACvB,SAAK,uBAAuB;AAC5B,SAAK,4BAA4B;AACjC,SAAK,kBAAkB;AAEvB,QAAI,KAAK,WAAY,eAAc,KAAK,UAAU;AAClD,QAAI,KAAK,WAAY,cAAa,KAAK,UAAU;AACjD,SAAK,eAAe;AACpB,SAAK,aAAa,YAAY,MAAM,KAAK,KAAK,MAAM,GAAG,GAAI;AAAA,EAC7D;AAAA,EAEA,aAAa,OAAgB,SAAkC;AAC7D,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAE/B,UAAM,UAAU,gBAAgB,KAAK;AACrC,UAAM,aAAa,cAAc,KAAK;AACtC,UAAM,iBAAiB,qBAAqB,SAAS,UAAU;AAE/D,UAAM,QAAkB,WAAW;AAAA,MACjC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,WAAW,aAAa,KAAK;AAAA,MAC7B,WAAW,KAAK,aAAa,WAAW;AAAA,MACxC,QAAQ,KAAK,OAAO;AAAA,MACpB,WAAW,KAAK,IAAI;AAAA,MACpB,YAAY,KAAK,OAAO,cAAc,KAAK,kBAAkB;AAAA,MAC7D,QAAQ,KAAK,OAAO,UAAU,WAAW;AAAA,MACzC,YAAY,KAAK,OAAO,cAAc,KAAK,OAAO;AAAA,MAClD,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,QAChC,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,aAAa,OAAiB;AAC5B,QAAI,CAAC,KAAK,OAAQ;AAClB,QAAI,CAAC,KAAK,kBAAkB,EAAG;AAE/B,UAAM,WAAqB,WAAW;AAAA,MACpC,GAAG;AAAA,MACH,WAAW,MAAM,aAAa,KAAK,aAAa,WAAW;AAAA,MAC3D,QAAQ,MAAM,UAAU,KAAK,OAAO;AAAA,MACpC,WAAW,MAAM,aAAa,KAAK,IAAI;AAAA,MACvC,YAAY,MAAM,cAAc,KAAK,OAAO,cAAc,KAAK,kBAAkB;AAAA,MACjF,QAAQ,MAAM,UAAU,KAAK,OAAO,UAAU,WAAW;AAAA,MACzD,YAAY,MAAM,cAAc,KAAK,OAAO,cAAc,KAAK,OAAO;AAAA,MACtE,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,EAEA,kBAAkB,YAAoB;AACpC,UAAM,YAAY,KAAK,IAAI;AAC3B,WAAO,MAAM;AACX,YAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAK,aAAa;AAAA,QAChB,MAAM;AAAA,QACN,SAAS,iBAAiB,UAAU;AAAA,QACpC,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ,UAAU,iBAAiB,QAAQ;AAAA,QAC7C;AAAA,QACA,MAAM,EAAE,QAAQ,WAAW;AAAA,MAC7B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,oBAAoB,SAAkB;AACpC,SAAK,aAAa;AAAA,MAChB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,WAAW,KAAK,IAAI;AAAA,MACpB,OAAO;AAAA,QACL,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,MACA,MAAM,UAAU,EAAE,QAAQ,IAAI;AAAA,IAChC,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB;AACtB,UAAM,WAAW,WAAW;AAC5B,SAAK,YAAY;AACjB,iBAAa,QAAQ,WAAW,EAC7B,KAAK,CAAC,WAA0B;AAC/B,UAAI,QAAQ;AACV,aAAK,YAAY;AACjB;AAAA,MACF;AACA,aAAO,aAAa,QAAQ,aAAa,QAAQ;AAAA,IACnD,CAAC,EACA,MAAM,MAAM;AAAA,IAEb,CAAC;AAAA,EACL;AAAA,EAEQ,oBAAyC;AAC/C,UAAM,QAAS,WAAmC;AAClD,QAAI,WAAW,OAAO,SAAS,MAAO,QAAO;AAC7C,WAAO;AAAA,EACT;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,EAEQ,sBAAsB;AAC5B,UAAM,aAAc,WAAmB;AACvC,QAAI,CAAC,cAAc,OAAO,WAAW,qBAAqB,YAAY;AACpE;AAAA,IACF;AACA,UAAM,WAAW,WAAW,mBAAmB;AAC/C,eAAW,iBAAiB,CAAC,OAAgB,YAAqB;AAChE,WAAK,aAAa,OAAO,EAAE,SAAS,OAAO,OAAO,EAAE,CAAC;AACrD,UAAI,OAAO,aAAa,YAAY;AAClC,iBAAS,OAAO,OAAO;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB;AAC1B,QAAI,KAAK,eAAgB;AACzB,QAAI,CAAC,cAAc,QAAS;AAC5B,SAAK,iBAAiB;AACtB,UAAM,WAAW,aAAa,QAAQ;AAAA,MACpC;AAAA,IACF;AACA,iBAAa,UAAU,OAAO,KAAa,UAAkB,SAAgB;AAC3E,UAAI;AACF,YAAI,cAAc,KAAK,GAAG,GAAG;AAC3B,gBAAM,iBACJ,sBAAsB,KAAK,KAAK,KAChC,sBAAsB,KAAK,KAAK,KAChC,gCAAgC,KAAK,KAAK,KAC1C,sCAAsC,KAAK,KAAK;AAClD,cAAI,gBAAgB;AAClB,iBAAK,aAAa;AAAA,cAChB,MAAM;AAAA,cACN,SAAS,2CAA2C,GAAG;AAAA,cACvD,WAAW,KAAK,IAAI;AAAA,cACpB,MAAM,EAAE,gBAAgB,sBAAsB;AAAA,YAChD,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AACA,WAAK;AACL,aAAO,SAAS,KAAK,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEQ,aAAa;AACnB,QAAI,KAAK,aAAc;AACvB,QAAI,OAAO,UAAU,WAAY;AACjC,SAAK,eAAe;AAEpB,UAAM,WAAW,MAAM,KAAK,UAAU;AACtC,IAAC,WAAmB,QAAQ,UAAU,SAAgB;AACpD,YAAM,QAAQ,KAAK,IAAI;AACvB,YAAM,WAAW,MAAM,SAAS,GAAG,IAAI;AACvC,YAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,UAAI;AACF,cAAM,UAAU,KAAK,CAAC;AACtB,cAAM,UACH,mBAAmB,UAAU,QAAQ,SAAS,KAAK,CAAC,GAAG,WACxD;AACF,cAAM,MAAM,mBAAmB,UAAU,QAAQ,MAAM,OAAO,OAAO;AAErE,YAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,eAAK,aAAa;AAAA,YAChB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,gBAAgB,SAAS;AAAA,YACzB,gBAAgB;AAAA,YAChB,WAAW,KAAK,IAAI;AAAA,YACpB,MAAM,EAAE,gBAAgB,gBAAgB;AAAA,UAC1C,CAAC;AAAA,QACH;AAEA,YAAI,WAAW,KAAM;AACnB,eAAK,aAAa;AAAA,YAChB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,eAAe;AAAA,YACf,gBAAgB,SAAS;AAAA,YACzB,gBAAgB;AAAA,YAChB,WAAW,KAAK,IAAI;AAAA,YACpB,OAAO;AAAA,cACL,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,QAAQ,UAAU,gBAAgB,QAAQ;AAAA,YAC5C;AAAA,UACF,CAAC;AAAA,QACH;AAEA,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,gBAAgB;AAAA,YAChB,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,yBAAyB;AAC/B,QAAI;AACF,cAAQ,iBAAiB,OAAO,CAAC,UAA2B;AAC1D,cAAM,MAAM,OAAO;AACnB,YAAI,CAAC,IAAK;AACV,YAAI;AACF,gBAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,gBAAM,SAA6B,CAAC;AACpC,iBAAO,aAAa,QAAQ,CAAC,OAAO,QAAQ;AAC1C,mBAAO,KAAK,CAAC,KAAK,KAAK,CAAC;AAAA,UAC1B,CAAC;AACD,gBAAM,YAAY,OAAO,KAAK,CAAC,CAAC,KAAK,KAAK,MAAwB;AAChE,gBAAI,cAAc,KAAK,GAAG,EAAG,QAAO;AACpC,mBAAO,wEAAwE;AAAA,cAC7E;AAAA,YACF;AAAA,UACF,CAAC;AACD,cAAI,WAAW;AACb,iBAAK,aAAa;AAAA,cAChB,MAAM;AAAA,cACN,SAAS;AAAA,cACT,WAAW,KAAK,IAAI;AAAA,cACpB,MAAM,EAAE,gBAAgB,iBAAiB;AAAA,cACzC,OAAO,EAAE,IAAI;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,8BAA8B;AACpC,QAAI;AACF,yBAAmB,YAAY,iBAAiB,MAAM;AACpD,aAAK,oBAAoB;AAAA,MAC3B,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,oBAAoB;AAC1B,uBAAmB,qBAAqB,MAAM;AAC5C,YAAM,WAAW,KAAK,IAAI,IAAI,KAAK;AACnC,WAAK,aAAa;AAAA,QAChB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW,KAAK,IAAI;AAAA,QACpB,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ,UAAU,aAAa,QAAQ;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,UAAM,YAAY,MAAM;AACtB,YAAM,QAAQ,KAAK,IAAI;AACvB,UAAI,SAAS;AACb,YAAM,OAAO,MAAM;AACjB,kBAAU;AACV,YAAI,KAAK,IAAI,IAAI,QAAQ,KAAM;AAC7B,gCAAsB,IAAI;AAAA,QAC5B,OAAO;AACL,gBAAM,MAAM;AACZ,eAAK,aAAa;AAAA,YAChB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,WAAW,KAAK,IAAI;AAAA,YACpB,OAAO;AAAA,cACL,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,QAAQ,UAAU,UAAU,GAAG;AAAA,YACjC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,4BAAsB,IAAI;AAAA,IAC5B;AAEA,cAAU;AACV,gBAAY,WAAW,GAAM;AAAA,EAC/B;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,MAC7B,CAAC;AACD,WAAK,eAAe;AACpB,UAAI,KAAK,YAAY;AACnB,qBAAa,KAAK,UAAU;AAC5B,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,gBAAgB;AACtB,UAAM,YAAY,KAAK,IAAI,KAAQ,MAAO,KAAK,KAAK,YAAY;AAChE,SAAK,eAAe,KAAK,IAAI,KAAK,eAAe,GAAG,CAAC;AACrD,QAAI,KAAK,YAAY;AACnB,mBAAa,KAAK,UAAU;AAAA,IAC9B;AACA,SAAK,aAAa,WAAW,MAAM,KAAK,KAAK,MAAM,GAAG,SAAS;AAAA,EACjE;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;AACF;AAEO,IAAM,UAAU,IAAI,UAAU;AAC9B,IAAM,OAAO,CAAC,WAA0B,QAAQ,KAAK,MAAM;AAC3D,IAAM,eAAe,CAAC,UAAmB,QAAQ,aAAa,KAAK;AACnE,IAAM,eAAe,CAAC,UAAoB,QAAQ,aAAa,KAAK;AACpE,IAAM,oBAAoB,CAAC,eAChC,QAAQ,kBAAkB,UAAU;AAC/B,IAAM,sBAAsB,CAAC,YAClC,QAAQ,oBAAoB,OAAO;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { RawEvent, Platform as VybeSecPlatform } from \"@vybesec/types\";\nimport AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport {\n DeviceEventEmitter,\n InteractionManager,\n Linking,\n Platform as RNPlatform\n} from \"react-native\";\n\nexport type VybeSecConfig = {\n key: string;\n environment?: \"production\" | \"staging\" | \"development\";\n platform?: VybeSecPlatform;\n release?: string;\n appVersion?: string;\n userId?: string;\n deviceType?: \"mobile\" | \"tablet\" | \"desktop\";\n osName?: string;\n sampleRate?: number;\n maxBuffer?: number;\n maxEventsPerMinute?: number;\n};\n\ntype InternalConfig = VybeSecConfig & {\n ingestUrl: string;\n};\n\nconst DEFAULT_INGEST_URL =\n \"https://vybesec-ingest.hexeldigitalstudio.workers.dev\";\nconst SESSION_KEY = \"vybesec_session_id\";\n\nfunction generateId(): string {\n return `vs_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\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\nconst SENSITIVE_KEY = /(password|token|secret|api[_-]?key|authorization)/i;\nconst MAX_SCRUB_DEPTH = 3;\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\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\nfunction detectSecuritySignal(message?: string, stack?: string): string | null {\n const combined = `${message ?? \"\"}\\n${stack ?? \"\"}`;\n if (/sk-[a-zA-Z0-9]{20,}/.test(combined)) return \"secret_key_exposed\";\n if (/pk_[a-zA-Z0-9]{20,}/.test(combined)) return \"public_key_exposed\";\n if (/Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(combined)) return \"bearer_token_exposed\";\n if (/api[_-]?key\\s*[:=]/i.test(combined)) return \"api_key_exposed\";\n return null;\n}\n\nfunction ratingFor(\n metric: string,\n value: number\n): \"good\" | \"needs_improvement\" | \"poor\" {\n const thresholds: Record<string, [number, number]> = {\n APP_START: [2000, 4000],\n SCREEN_RENDER: [1000, 2500],\n JS_FPS: [55, 30],\n SLOW_NETWORK: [3000, 7000]\n };\n const [good, poor] = thresholds[metric] ?? [0, 0];\n if (metric === \"JS_FPS\") {\n if (value >= good) return \"good\";\n if (value >= poor) return \"needs_improvement\";\n return \"poor\";\n }\n if (value <= good) return \"good\";\n if (value <= poor) return \"needs_improvement\";\n return \"poor\";\n}\n\nasync function setupPromiseRejectionTracking(\n onUnhandled: (error: unknown) => void\n) {\n try {\n const promiseImpl = await import(\"promise/setimmediate/es6-extensions\");\n const rejectionTracking = await import(\n \"promise/setimmediate/rejection-tracking\"\n );\n const PromiseImpl =\n (promiseImpl as unknown as { default?: PromiseConstructor }).default ??\n (promiseImpl as unknown as PromiseConstructor);\n if (PromiseImpl) {\n (globalThis as any).Promise = PromiseImpl;\n }\n const enable =\n (rejectionTracking as unknown as { enable?: Function }).enable ??\n (rejectionTracking as unknown as Function);\n if (typeof enable === \"function\") {\n enable({\n allRejections: true,\n onUnhandled: (_id: number, error: unknown) => onUnhandled(error)\n });\n }\n } catch {\n // ignore rejection tracking failures\n }\n}\n\nexport class VybeSecRN {\n private config: InternalConfig | null = null;\n private buffer: RawEvent[] = [];\n private eventTimestamps: number[] = [];\n private flushTimer?: ReturnType<typeof setInterval>;\n private retryTimer?: ReturnType<typeof setTimeout>;\n private retryAttempt = 0;\n private isFlushing = false;\n private sessionId?: string;\n private patchedStorage = false;\n private patchedFetch = false;\n private startTime = Date.now();\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: DEFAULT_INGEST_URL,\n platform: config.platform ?? \"react-native\"\n };\n\n this.initSessionId();\n this.startTime = Date.now();\n\n this.installErrorHandler();\n void setupPromiseRejectionTracking((error) => this.captureError(error));\n this.patchFetch();\n this.patchAsyncStorage();\n this.attachDeepLinkListener();\n this.attachMemoryWarningListener();\n this.startPerfMonitors();\n\n if (this.flushTimer) clearInterval(this.flushTimer);\n if (this.retryTimer) clearTimeout(this.retryTimer);\n this.retryAttempt = 0;\n this.flushTimer = setInterval(() => void 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 message = getErrorMessage(error);\n const stackTrace = getStackTrace(error);\n const securitySignal = detectSecuritySignal(message, stackTrace);\n\n const event: RawEvent = scrubEvent({\n type: \"error\",\n message,\n stackTrace,\n errorType: getErrorType(error),\n sessionId: this.sessionId ?? generateId(),\n userId: this.config.userId,\n timestamp: Date.now(),\n deviceType: this.config.deviceType ?? this.defaultDeviceType(),\n osName: this.config.osName ?? RNPlatform.OS,\n appVersion: this.config.appVersion ?? this.config.release,\n tags: {\n ...(context ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\",\n ...(securitySignal ? { securitySignal } : {})\n }\n });\n\n this.pushEvent(event);\n }\n\n captureEvent(event: RawEvent) {\n if (!this.config) return;\n if (!this.shouldAcceptEvent()) return;\n\n const enriched: RawEvent = scrubEvent({\n ...event,\n sessionId: event.sessionId ?? this.sessionId ?? generateId(),\n userId: event.userId ?? this.config.userId,\n timestamp: event.timestamp ?? Date.now(),\n deviceType: event.deviceType ?? this.config.deviceType ?? this.defaultDeviceType(),\n osName: event.osName ?? this.config.osName ?? RNPlatform.OS,\n appVersion: event.appVersion ?? this.config.appVersion ?? this.config.release,\n tags: {\n ...(event.tags ?? {}),\n platform: this.config.platform ?? \"react-native\",\n environment: this.config.environment ?? \"production\",\n release: this.config.release ?? \"\"\n }\n });\n\n this.pushEvent(enriched);\n }\n\n trackScreenRender(screenName: string) {\n const startedAt = Date.now();\n return () => {\n const duration = Date.now() - startedAt;\n this.captureEvent({\n type: \"performance\",\n message: `Screen render ${screenName}`,\n timestamp: Date.now(),\n extra: {\n metricName: \"SCREEN_RENDER\",\n value: duration,\n rating: ratingFor(\"SCREEN_RENDER\", duration)\n },\n tags: { screen: screenName }\n });\n };\n }\n\n notifyMemoryWarning(details?: string) {\n this.captureEvent({\n type: \"performance\",\n message: \"Memory warning\",\n timestamp: Date.now(),\n extra: {\n metricName: \"MEMORY_WARNING\",\n value: 1,\n rating: \"needs_improvement\"\n },\n tags: details ? { details } : undefined\n });\n }\n\n private initSessionId() {\n const fallback = generateId();\n this.sessionId = fallback;\n AsyncStorage.getItem(SESSION_KEY)\n .then((stored: string | null) => {\n if (stored) {\n this.sessionId = stored;\n return;\n }\n return AsyncStorage.setItem(SESSION_KEY, fallback);\n })\n .catch(() => {\n // ignore storage failures\n });\n }\n\n private defaultDeviceType(): \"mobile\" | \"tablet\" {\n const isPad = (RNPlatform as { isPad?: boolean }).isPad;\n if (RNPlatform.OS === \"ios\" && isPad) return \"tablet\";\n return \"mobile\";\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 installErrorHandler() {\n const ErrorUtils = (globalThis as any).ErrorUtils;\n if (!ErrorUtils || typeof ErrorUtils.setGlobalHandler !== \"function\") {\n return;\n }\n const previous = ErrorUtils.getGlobalHandler?.();\n ErrorUtils.setGlobalHandler((error: unknown, isFatal: boolean) => {\n this.captureError(error, { isFatal: String(isFatal) });\n if (typeof previous === \"function\") {\n previous(error, isFatal);\n }\n });\n }\n\n private patchAsyncStorage() {\n if (this.patchedStorage) return;\n if (!AsyncStorage?.setItem) return;\n this.patchedStorage = true;\n const original = AsyncStorage.setItem.bind(\n AsyncStorage\n ) as unknown as (...args: any[]) => Promise<void>;\n AsyncStorage.setItem = async (key: string, value: string, ...rest: any[]) => {\n try {\n if (SENSITIVE_KEY.test(key)) {\n const looksSensitive =\n /sk-[a-zA-Z0-9]{20,}/.test(value) ||\n /pk_[a-zA-Z0-9]{20,}/.test(value) ||\n /Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(value) ||\n /eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\./.test(value);\n if (looksSensitive) {\n this.captureEvent({\n type: \"warning\",\n message: `Sensitive token stored in AsyncStorage (${key})`,\n timestamp: Date.now(),\n tags: { securitySignal: \"async_storage_token\" }\n });\n }\n }\n } catch {\n // ignore\n }\n void rest;\n return original(key, value);\n };\n }\n\n private patchFetch() {\n if (this.patchedFetch) return;\n if (typeof fetch !== \"function\") return;\n this.patchedFetch = true;\n\n const original = fetch.bind(globalThis) as (...args: any[]) => Promise<Response>;\n (globalThis as any).fetch = async (...args: any[]) => {\n const start = Date.now();\n const response = await original(...args);\n const duration = Date.now() - start;\n\n try {\n const request = args[0];\n const method =\n (request instanceof Request ? request.method : args[1]?.method) ??\n \"GET\";\n const url = request instanceof Request ? request.url : String(request);\n\n if (url.startsWith(\"http://\")) {\n this.captureEvent({\n type: \"warning\",\n message: \"Insecure HTTP request detected\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n tags: { securitySignal: \"insecure_http\" }\n });\n }\n\n if (duration > 3000) {\n this.captureEvent({\n type: \"performance\",\n message: \"Slow network call\",\n requestUrl: url,\n requestMethod: method,\n responseStatus: response.status,\n responseTimeMs: duration,\n timestamp: Date.now(),\n extra: {\n metricName: \"SLOW_NETWORK\",\n value: duration,\n rating: ratingFor(\"SLOW_NETWORK\", duration)\n }\n });\n }\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 responseTimeMs: duration,\n timestamp: Date.now()\n });\n }\n } catch {\n // ignore fetch instrumentation failures\n }\n\n return response;\n };\n }\n\n private attachDeepLinkListener() {\n try {\n Linking.addEventListener(\"url\", (event: { url: string }) => {\n const url = event?.url;\n if (!url) return;\n try {\n const parsed = new URL(url);\n const params: [string, string][] = [];\n parsed.searchParams.forEach((value, key) => {\n params.push([key, value]);\n });\n const sensitive = params.find(([key, value]: [string, string]) => {\n if (SENSITIVE_KEY.test(key)) return true;\n return /sk-[a-zA-Z0-9]{20,}|pk_[a-zA-Z0-9]{20,}|Bearer\\s+[a-zA-Z0-9\\-_.]{20,}/.test(\n value\n );\n });\n if (sensitive) {\n this.captureEvent({\n type: \"warning\",\n message: \"Sensitive data detected in deep link\",\n timestamp: Date.now(),\n tags: { securitySignal: \"deep_link_leak\" },\n extra: { url }\n });\n }\n } catch {\n // ignore\n }\n });\n } catch {\n // ignore linking errors\n }\n }\n\n private attachMemoryWarningListener() {\n try {\n DeviceEventEmitter.addListener(\"memoryWarning\", () => {\n this.notifyMemoryWarning();\n });\n } catch {\n // ignore\n }\n }\n\n private startPerfMonitors() {\n InteractionManager.runAfterInteractions(() => {\n const duration = Date.now() - this.startTime;\n this.captureEvent({\n type: \"performance\",\n message: \"App start\",\n timestamp: Date.now(),\n extra: {\n metricName: \"APP_START\",\n value: duration,\n rating: ratingFor(\"APP_START\", duration)\n }\n });\n });\n\n const sampleFps = () => {\n const start = Date.now();\n let frames = 0;\n const loop = () => {\n frames += 1;\n if (Date.now() - start < 1000) {\n requestAnimationFrame(loop);\n } else {\n const fps = frames;\n this.captureEvent({\n type: \"performance\",\n message: \"JS thread FPS\",\n timestamp: Date.now(),\n extra: {\n metricName: \"JS_FPS\",\n value: fps,\n rating: ratingFor(\"JS_FPS\", fps)\n }\n });\n }\n };\n requestAnimationFrame(loop);\n };\n\n sampleFps();\n setInterval(sampleFps, 30_000);\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 });\n this.retryAttempt = 0;\n if (this.retryTimer) {\n 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 scheduleRetry() {\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 clearTimeout(this.retryTimer);\n }\n this.retryTimer = setTimeout(() => void 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\nexport const vybesec = new VybeSecRN();\nexport const init = (config: VybeSecConfig) => vybesec.init(config);\nexport const captureError = (error: unknown) => vybesec.captureError(error);\nexport const captureEvent = (event: RawEvent) => vybesec.captureEvent(event);\nexport const trackScreenRender = (screenName: string) =>\n vybesec.trackScreenRender(screenName);\nexport const notifyMemoryWarning = (details?: string) =>\n vybesec.notifyMemoryWarning(details);\n"],"mappings":"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","names":[]}
|