appdoctor-rn 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/index.cjs +20 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -10,6 +10,10 @@ npm install appdoctor-rn
|
|
|
10
10
|
|
|
11
11
|
Peer dependencies: `react`, `react-native`. Optional: `@react-navigation/native` for stack/tab navigation listeners.
|
|
12
12
|
|
|
13
|
+
## Package
|
|
14
|
+
|
|
15
|
+
- npm: [appdoctor-rn](https://www.npmjs.com/package/appdoctor-rn)
|
|
16
|
+
|
|
13
17
|
## Quick start
|
|
14
18
|
|
|
15
19
|
1. Wrap your app with `AppDoctorProvider` and pass transports (for example `createConsoleTransport()`).
|
package/dist/index.cjs
CHANGED
|
@@ -236,6 +236,7 @@ function createConsoleTransport(options = {}) {
|
|
|
236
236
|
const label = options.label ?? "AppDoctor";
|
|
237
237
|
const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1e3;
|
|
238
238
|
const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;
|
|
239
|
+
const format = options.format ?? "pretty";
|
|
239
240
|
function toHint(event) {
|
|
240
241
|
if (event.name === "screen_load" && event.phase === "ready" && event.durationMs >= slowScreenThresholdMs) {
|
|
241
242
|
return `Slow screen "${event.screen}" (${event.durationMs}ms). Check expensive effects and repeated renders.`;
|
|
@@ -245,6 +246,19 @@ function createConsoleTransport(options = {}) {
|
|
|
245
246
|
}
|
|
246
247
|
return void 0;
|
|
247
248
|
}
|
|
249
|
+
function toPrettyLine(event) {
|
|
250
|
+
if (event.name === "screen_load") {
|
|
251
|
+
return `screen ${event.screen} phase=${event.phase} duration=${event.durationMs}ms`;
|
|
252
|
+
}
|
|
253
|
+
if (event.name === "api_request") {
|
|
254
|
+
const status = event.status ?? "n/a";
|
|
255
|
+
return `api ${event.method} ${event.url} status=${status} duration=${event.durationMs}ms success=${event.success}`;
|
|
256
|
+
}
|
|
257
|
+
if (event.name === "render_event") {
|
|
258
|
+
return `render ${event.component} count=${event.renderCount}`;
|
|
259
|
+
}
|
|
260
|
+
return `sdk_error ${event.message}`;
|
|
261
|
+
}
|
|
248
262
|
return {
|
|
249
263
|
send(events) {
|
|
250
264
|
if (events.length === 0) return;
|
|
@@ -253,8 +267,13 @@ function createConsoleTransport(options = {}) {
|
|
|
253
267
|
if (hint) {
|
|
254
268
|
console.warn(`[${label}] ${hint}`);
|
|
255
269
|
}
|
|
270
|
+
if (format === "pretty") {
|
|
271
|
+
console.log(`[${label}] ${toPrettyLine(event)}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (format === "raw") {
|
|
275
|
+
console.log(`[${label}]`, events);
|
|
256
276
|
}
|
|
257
|
-
console.log(`[${label}]`, events);
|
|
258
277
|
}
|
|
259
278
|
};
|
|
260
279
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/core/sampling.ts","../src/core/client.ts","../src/transports/console-transport.ts","../src/transports/http-transport.ts","../src/navigation/route-name.ts","../src/navigation/create-navigation-listener.ts","../src/network/axios-instrumentation.ts","../src/utils/track-api.ts","../src/provider/context.ts","../src/provider/AppDoctorProvider.tsx","../src/hooks/useAppDoctor.ts","../src/hooks/useTrackScreen.ts","../src/hooks/useTrackRender.ts"],"names":["createContext","useRef","useEffect","useContext"],"mappings":"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","file":"index.cjs","sourcesContent":["export type AppDoctorEventName =\n | \"screen_load\"\n | \"api_request\"\n | \"render_event\"\n | \"sdk_error\";\n\nexport interface EventContext {\n route?: string;\n component?: string;\n platform?: string;\n appVersion?: string;\n metadata?: Record<string, string | number | boolean>;\n}\n\nexport interface AppDoctorEventBase {\n name: AppDoctorEventName;\n /** Unix ms */\n timestamp: number;\n sessionId: string;\n tags?: Record<string, string>;\n context?: EventContext;\n}\n\nexport interface ScreenLoadEvent extends AppDoctorEventBase {\n name: \"screen_load\";\n screen: string;\n phase: \"start\" | \"ready\";\n /** Time from navigation intent to ready signal (ms), if known */\n durationMs: number;\n}\n\nexport interface NetworkRequestEvent extends AppDoctorEventBase {\n name: \"api_request\";\n method: string;\n url: string;\n status?: number;\n durationMs: number;\n success: boolean;\n errorMessage?: string;\n}\n\nexport interface RenderCountEvent extends AppDoctorEventBase {\n name: \"render_event\";\n component: string;\n renderCount: number;\n}\n\nexport interface SdkErrorEvent extends AppDoctorEventBase {\n name: \"sdk_error\";\n message: string;\n stack?: string;\n errorContext?: string;\n}\n\nexport type AppDoctorEvent =\n | ScreenLoadEvent\n | NetworkRequestEvent\n | RenderCountEvent\n | SdkErrorEvent;\n\n/** Payload accepted by `AppDoctorClient.emit` (union; avoids `Omit` pitfalls on unions). */\nexport type AppDoctorEmitInput =\n | Omit<ScreenLoadEvent, \"timestamp\" | \"sessionId\">\n | Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\">\n | Omit<RenderCountEvent, \"timestamp\" | \"sessionId\">\n | Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\">;\n\nexport interface Transport {\n send(events: readonly AppDoctorEvent[]): void | Promise<void>;\n flush?: () => void | Promise<void>;\n shutdown?: () => void | Promise<void>;\n}\n\nexport interface AppDoctorConfig {\n enabled?: boolean;\n /** Shortcut to disable all internal work while preserving integration calls */\n noop?: boolean;\n /** 0–1, default 1 */\n sampleRate?: number;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n transports?: Transport[];\n tags?: Record<string, string>;\n /** Add context to every emitted event */\n context?: EventContext;\n /** When true, wraps global fetch (restore on shutdown) */\n instrumentFetch?: boolean;\n /**\n * Redacts/sanitizes network event fields before emission.\n * Returning partial values overrides the computed payload.\n */\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nexport const DEFAULT_FLUSH_INTERVAL_MS = 2000;\nexport const DEFAULT_MAX_QUEUE_SIZE = 200;\n","export function shouldSample(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n","import type {\n AppDoctorConfig,\n AppDoctorEmitInput,\n AppDoctorEvent,\n NetworkRequestEvent,\n SdkErrorEvent,\n Transport,\n} from \"./types.js\";\nimport {\n DEFAULT_FLUSH_INTERVAL_MS,\n DEFAULT_MAX_QUEUE_SIZE,\n} from \"./types.js\";\nimport { shouldSample } from \"./sampling.js\";\n\nfunction now(): number {\n return Date.now();\n}\n\nfunction newSessionId(): string {\n return `${now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class AppDoctorClient {\n readonly sessionId: string;\n private readonly config: Required<\n Pick<\n AppDoctorConfig,\n | \"enabled\"\n | \"noop\"\n | \"sampleRate\"\n | \"flushIntervalMs\"\n | \"maxQueueSize\"\n | \"instrumentFetch\"\n >\n > &\n Pick<AppDoctorConfig, \"tags\" | \"context\" | \"redactNetworkEvent\">;\n private readonly transports: Transport[];\n private queue: AppDoctorEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | undefined;\n private fetchPatched = false;\n private originalFetch: typeof fetch | undefined;\n\n constructor(config: AppDoctorConfig = {}) {\n this.sessionId = newSessionId();\n this.config = {\n enabled: config.enabled ?? true,\n noop: config.noop ?? false,\n sampleRate: config.sampleRate ?? 1,\n flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n maxQueueSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n instrumentFetch: config.instrumentFetch ?? true,\n tags: config.tags,\n context: config.context,\n redactNetworkEvent: config.redactNetworkEvent,\n };\n this.transports = [...(config.transports ?? [])];\n if (this.config.enabled) {\n this.startFlushTimer();\n if (this.config.instrumentFetch && typeof globalThis.fetch === \"function\") {\n this.patchFetch();\n }\n }\n }\n\n updateConfig(partial: Partial<AppDoctorConfig>): void {\n if (partial.enabled !== undefined) {\n (this.config as { enabled: boolean }).enabled = partial.enabled;\n }\n if (partial.noop !== undefined) {\n (this.config as { noop: boolean }).noop = partial.noop;\n }\n if (partial.sampleRate !== undefined) {\n (this.config as { sampleRate: number }).sampleRate = partial.sampleRate;\n }\n if (partial.flushIntervalMs !== undefined) {\n (this.config as { flushIntervalMs: number }).flushIntervalMs =\n partial.flushIntervalMs;\n this.restartFlushTimer();\n }\n if (partial.maxQueueSize !== undefined) {\n (this.config as { maxQueueSize: number }).maxQueueSize =\n partial.maxQueueSize;\n }\n if (partial.tags !== undefined) {\n this.config.tags = partial.tags;\n }\n if (partial.context !== undefined) {\n this.config.context = partial.context;\n }\n if (partial.instrumentFetch !== undefined) {\n const next = partial.instrumentFetch;\n (this.config as { instrumentFetch: boolean }).instrumentFetch = next;\n if (next && !this.fetchPatched) this.patchFetch();\n if (!next && this.fetchPatched) this.restoreFetch();\n }\n if (partial.transports !== undefined) {\n this.transports.length = 0;\n this.transports.push(...partial.transports);\n }\n if (partial.redactNetworkEvent !== undefined) {\n this.config.redactNetworkEvent = partial.redactNetworkEvent;\n }\n }\n\n addTransport(transport: Transport): void {\n this.transports.push(transport);\n }\n\n emit(event: AppDoctorEmitInput): void {\n if (!this.config.enabled) return;\n if (this.config.noop) return;\n if (!shouldSample(this.config.sampleRate)) return;\n\n const { tags: eventTags, ...payload } = event;\n const tags =\n this.config.tags || eventTags\n ? { ...this.config.tags, ...eventTags }\n : undefined;\n\n const full = {\n ...payload,\n timestamp: now(),\n sessionId: this.sessionId,\n tags,\n context: this.config.context,\n } as AppDoctorEvent;\n\n this.enqueue(full);\n }\n\n private enqueue(event: AppDoctorEvent): void {\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift();\n }\n this.queue.push(event);\n }\n\n captureError(message: string, context?: string, err?: unknown): void {\n const stack =\n err instanceof Error && typeof err.stack === \"string\"\n ? err.stack\n : undefined;\n const sdkErr: Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\" | \"tags\"> = {\n name: \"sdk_error\",\n message,\n stack,\n errorContext: context,\n };\n this.emit(sdkErr);\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n await Promise.all(\n this.transports.map(async (t) => {\n try {\n await t.send(batch);\n } catch (e) {\n this.safeInternalError(\"transport.send failed\", e);\n }\n }),\n );\n }\n\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n this.restoreFetch();\n await this.flush();\n await Promise.all(\n this.transports.map(async (t) => {\n if (!t.shutdown) return;\n try {\n await t.shutdown();\n } catch (e) {\n this.safeInternalError(\"transport.shutdown failed\", e);\n }\n }),\n );\n }\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushIntervalMs);\n if (\n typeof this.flushTimer === \"object\" &&\n this.flushTimer &&\n \"unref\" in this.flushTimer &&\n typeof this.flushTimer.unref === \"function\"\n ) {\n this.flushTimer.unref();\n }\n }\n\n private restartFlushTimer(): void {\n if (this.flushTimer) clearInterval(this.flushTimer);\n this.startFlushTimer();\n }\n\n private safeInternalError(msg: string, err: unknown): void {\n const dev =\n typeof __DEV__ !== \"undefined\"\n ? __DEV__\n : typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n if (dev) console.warn(`[AppDoctor] ${msg}`, err);\n }\n\n private patchFetch(): void {\n if (this.fetchPatched) return;\n const g = globalThis as { fetch: typeof fetch };\n this.originalFetch = g.fetch.bind(globalThis);\n const originalFetch = this.originalFetch;\n g.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const start = now();\n let method = \"GET\";\n let url = \"\";\n try {\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.href;\n } else if (typeof Request !== \"undefined\" && input instanceof Request) {\n url = input.url;\n method = input.method;\n }\n if (init?.method) method = init.method;\n } catch {\n /* ignore */\n }\n\n const urlForEvent =\n url ||\n (typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : typeof Request !== \"undefined\" && input instanceof Request\n ? input.url\n : \"[request]\");\n\n try {\n const res = await originalFetch(input, init);\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n status: res.status,\n durationMs,\n success: true,\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n return res;\n } catch (e) {\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n durationMs,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n throw e;\n }\n };\n this.fetchPatched = true;\n }\n\n private restoreFetch(): void {\n if (!this.fetchPatched || !this.originalFetch) return;\n (globalThis as { fetch: typeof fetch }).fetch = this.originalFetch;\n this.fetchPatched = false;\n this.originalFetch = undefined;\n }\n\n private applyNetworkRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n if (!this.config.redactNetworkEvent) return event;\n const redacted = this.config.redactNetworkEvent(event);\n return { ...event, ...redacted };\n }\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport function createConsoleTransport(\n options: {\n label?: string;\n slowScreenThresholdMs?: number;\n slowApiThresholdMs?: number;\n } = {},\n): Transport {\n const label = options.label ?? \"AppDoctor\";\n const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1000;\n const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;\n\n function toHint(event: AppDoctorEvent): string | undefined {\n if (\n event.name === \"screen_load\" &&\n event.phase === \"ready\" &&\n event.durationMs >= slowScreenThresholdMs\n ) {\n return `Slow screen \"${event.screen}\" (${event.durationMs}ms). Check expensive effects and repeated renders.`;\n }\n if (event.name === \"api_request\" && event.durationMs >= slowApiThresholdMs) {\n return `Slow API \"${event.method} ${event.url}\" (${event.durationMs}ms). Check server latency, payload size, and retry loops.`;\n }\n return undefined;\n }\n\n return {\n send(events: readonly AppDoctorEvent[]): void {\n if (events.length === 0) return;\n for (const event of events) {\n const hint = toHint(event);\n if (hint) {\n console.warn(`[${label}] ${hint}`);\n }\n }\n console.log(`[${label}]`, events);\n },\n };\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface HttpTransportOptions {\n url: string;\n headers?: Record<string, string>;\n maxRetries?: number;\n /** ms */\n initialBackoffMs?: number;\n getExtraBody?: () => Record<string, unknown>;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((r) => setTimeout(r, ms));\n}\n\nexport function createHttpTransport(options: HttpTransportOptions): Transport {\n const maxRetries = options.maxRetries ?? 3;\n const initialBackoffMs = options.initialBackoffMs ?? 500;\n\n return {\n async send(events: readonly AppDoctorEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = {\n events: [...events],\n ...(options.getExtraBody?.() ?? {}),\n };\n let attempt = 0;\n let backoff = initialBackoffMs;\n for (;;) {\n try {\n const res = await fetch(options.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: JSON.stringify(body),\n });\n if (res.ok) return;\n if (res.status >= 400 && res.status < 500 && res.status !== 429) {\n return;\n }\n } catch {\n /* retry */\n }\n attempt += 1;\n if (attempt > maxRetries) return;\n await sleep(backoff);\n backoff *= 2;\n }\n },\n };\n}\n","/**\n * Best-effort active route name from React Navigation state tree.\n * Avoids a hard dependency on `@react-navigation/native` types at runtime.\n */\nexport function getActiveRouteName(state: unknown): string | undefined {\n if (!state || typeof state !== \"object\") return undefined;\n const s = state as {\n index?: number;\n routes?: Array<{ name?: string; state?: unknown }>;\n };\n if (!Array.isArray(s.routes) || typeof s.index !== \"number\") return undefined;\n const route = s.routes[s.index];\n if (!route || typeof route !== \"object\") return undefined;\n if (route.state !== undefined) return getActiveRouteName(route.state);\n return typeof route.name === \"string\" ? route.name : undefined;\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport { getActiveRouteName } from \"./route-name.js\";\n\nexport interface NavigationTimingState {\n lastScreen?: string;\n}\n\n/**\n * Pass the returned listener to `NavigationContainer` as `onStateChange`.\n * Emits `screen_load` when the active route changes and a ready event after the next microtask\n * (approximates first paint/commit after navigation state updates).\n */\nexport function createNavigationStateListener(client: AppDoctorClient): {\n listener: (state: unknown) => void;\n reset: () => void;\n} {\n const timing: NavigationTimingState = {};\n\n return {\n listener(state: unknown) {\n const screen = getActiveRouteName(state);\n if (!screen || screen === timing.lastScreen) return;\n\n timing.lastScreen = screen;\n const startedAt = Date.now();\n\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n\n queueMicrotask(() => {\n if (timing.lastScreen !== screen) return;\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n },\n reset() {\n timing.lastScreen = undefined;\n },\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport type { NetworkRequestEvent } from \"../core/types.js\";\n\n/** Minimal Axios shape to avoid requiring `axios` as a dependency. */\nexport interface AxiosLike {\n interceptors: {\n request: {\n use: (onFulfilled: (value: unknown) => unknown) => number;\n eject: (id: number) => void;\n };\n response: {\n use: (\n onFulfilled: (value: unknown) => unknown,\n onRejected?: (error: unknown) => unknown,\n ) => number;\n eject: (id: number) => void;\n };\n };\n}\n\nexport interface AxiosInstrumentationOptions {\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nfunction getConfig(errorOrResponse: unknown): unknown {\n if (!errorOrResponse || typeof errorOrResponse !== \"object\") return undefined;\n if (\n \"config\" in errorOrResponse &&\n errorOrResponse.config &&\n typeof errorOrResponse.config === \"object\"\n ) {\n return errorOrResponse.config;\n }\n return undefined;\n}\n\nfunction getResponseMeta(response: unknown): {\n status?: number;\n method?: string;\n url?: string;\n} {\n if (!response || typeof response !== \"object\") return {};\n const r = response;\n const status =\n \"status\" in r && typeof r.status === \"number\" ? r.status : undefined;\n const rawConfig = \"config\" in r ? r.config : undefined;\n let method: string | undefined;\n let url: string | undefined;\n if (rawConfig !== null && typeof rawConfig === \"object\") {\n if (\"method\" in rawConfig && typeof rawConfig.method === \"string\") {\n method = rawConfig.method;\n }\n if (\"url\" in rawConfig && typeof rawConfig.url === \"string\") {\n url = rawConfig.url;\n }\n }\n return {\n status,\n method,\n url,\n };\n}\n\n/**\n * Returns an `eject` function to remove interceptors.\n */\nexport function instrumentAxios(\n axios: AxiosLike,\n client: AppDoctorClient,\n options: AxiosInstrumentationOptions = {},\n): () => void {\n function applyRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n const redacted = options.redactNetworkEvent?.(event);\n return redacted ? { ...event, ...redacted } : event;\n }\n\n const starts = new WeakMap<object, number>();\n\n const reqId = axios.interceptors.request.use((config) => {\n if (config !== null && typeof config === \"object\") {\n starts.set(config, Date.now());\n }\n return config;\n });\n\n const resId = axios.interceptors.response.use(\n (response) => {\n const cfg = getConfig(response);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n const { status, method, url } = getResponseMeta(response);\n const event = applyRedaction({\n method: (method ?? \"GET\").toUpperCase(),\n url: url ?? \"\",\n status,\n durationMs: Date.now() - start,\n success: true,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n return response;\n },\n (error: unknown) => {\n const cfg = getConfig(error);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n let method = \"GET\";\n let url = \"\";\n let status: number | undefined;\n let errorMessage = String(error);\n if (error !== null && typeof error === \"object\") {\n if (\"message\" in error && typeof error.message === \"string\") {\n errorMessage = error.message;\n }\n const resp =\n \"response\" in error && error.response !== null &&\n typeof error.response === \"object\"\n ? error.response\n : undefined;\n if (\n resp &&\n \"status\" in resp &&\n typeof resp.status === \"number\"\n ) {\n status = resp.status;\n }\n const errCfg =\n \"config\" in error && error.config !== null &&\n typeof error.config === \"object\"\n ? error.config\n : undefined;\n if (errCfg) {\n if (\"method\" in errCfg && typeof errCfg.method === \"string\") {\n method = errCfg.method.toUpperCase();\n }\n if (\"url\" in errCfg && typeof errCfg.url === \"string\") {\n url = errCfg.url;\n }\n }\n }\n const event = applyRedaction({\n method,\n url,\n status,\n durationMs: Date.now() - start,\n success: false,\n errorMessage,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n const rejectReason =\n error instanceof Error ? error : new Error(String(error));\n return Promise.reject(rejectReason);\n },\n );\n\n return () => {\n axios.interceptors.request.eject(reqId);\n axios.interceptors.response.eject(resId);\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\n\n/**\n * Wraps an async call and emits an `api_request` event with a synthetic URL label.\n */\nexport async function trackApi<T>(\n client: AppDoctorClient,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const start = Date.now();\n try {\n const result = await fn();\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n status: 200,\n durationMs: Date.now() - start,\n success: true,\n });\n return result;\n } catch (e) {\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n durationMs: Date.now() - start,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n throw e;\n }\n}\n","import { createContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\n\nexport const AppDoctorContext = createContext<AppDoctorClient | null>(null);\n","import { useEffect, useRef, type ReactElement, type ReactNode } from \"react\";\nimport { AppDoctorClient } from \"../core/client.js\";\nimport type { AppDoctorConfig } from \"../core/types.js\";\nimport { AppDoctorContext } from \"./context.js\";\n\nexport type AppDoctorProviderProps = AppDoctorConfig & {\n children: ReactNode;\n};\n\nexport function AppDoctorProvider({\n children,\n ...config\n}: AppDoctorProviderProps): ReactElement {\n const clientRef = useRef<AppDoctorClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new AppDoctorClient(config);\n }\n\n const {\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n } = config;\n\n useEffect(() => {\n clientRef.current?.updateConfig({\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n });\n }, [\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n ]);\n\n useEffect(() => {\n return () => {\n void clientRef.current?.shutdown();\n clientRef.current = null;\n };\n }, []);\n\n return (\n <AppDoctorContext.Provider value={clientRef.current}>\n {children}\n </AppDoctorContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport function useAppDoctor(): AppDoctorClient {\n const client = useContext(AppDoctorContext);\n if (!client) {\n throw new Error(\"useAppDoctor must be used within AppDoctorProvider\");\n }\n return client;\n}\n","import { useContext, useEffect } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackScreenOptions {\n client?: AppDoctorClient;\n}\n\n/**\n * Emits `screen_load` lifecycle events on mount and ready.\n */\nexport function useTrackScreen(\n screen: string,\n options: UseTrackScreenOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackScreen requires AppDoctorProvider or options.client\",\n );\n }\n\n useEffect(() => {\n const startedAt = Date.now();\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n queueMicrotask(() => {\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n }, [client, screen]);\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackRenderOptions {\n client?: AppDoctorClient;\n /** Emit every N renders (default 10) to limit noise */\n every?: number;\n}\n\n/**\n * Emits `render_event` periodically when the component re-renders.\n */\nexport function useTrackRender(\n componentName: string,\n options: UseTrackRenderOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackRender requires AppDoctorProvider or options.client\",\n );\n }\n const every = options.every ?? 10;\n const count = useRef(0);\n\n count.current += 1;\n\n useEffect(() => {\n if (count.current % every !== 0) return;\n client.emit({\n name: \"render_event\",\n component: componentName,\n renderCount: count.current,\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/core/sampling.ts","../src/core/client.ts","../src/transports/console-transport.ts","../src/transports/http-transport.ts","../src/navigation/route-name.ts","../src/navigation/create-navigation-listener.ts","../src/network/axios-instrumentation.ts","../src/utils/track-api.ts","../src/provider/context.ts","../src/provider/AppDoctorProvider.tsx","../src/hooks/useAppDoctor.ts","../src/hooks/useTrackScreen.ts","../src/hooks/useTrackRender.ts"],"names":["createContext","useRef","useEffect","useContext"],"mappings":"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","file":"index.cjs","sourcesContent":["export type AppDoctorEventName =\n | \"screen_load\"\n | \"api_request\"\n | \"render_event\"\n | \"sdk_error\";\n\nexport interface EventContext {\n route?: string;\n component?: string;\n platform?: string;\n appVersion?: string;\n metadata?: Record<string, string | number | boolean>;\n}\n\nexport interface AppDoctorEventBase {\n name: AppDoctorEventName;\n /** Unix ms */\n timestamp: number;\n sessionId: string;\n tags?: Record<string, string>;\n context?: EventContext;\n}\n\nexport interface ScreenLoadEvent extends AppDoctorEventBase {\n name: \"screen_load\";\n screen: string;\n phase: \"start\" | \"ready\";\n /** Time from navigation intent to ready signal (ms), if known */\n durationMs: number;\n}\n\nexport interface NetworkRequestEvent extends AppDoctorEventBase {\n name: \"api_request\";\n method: string;\n url: string;\n status?: number;\n durationMs: number;\n success: boolean;\n errorMessage?: string;\n}\n\nexport interface RenderCountEvent extends AppDoctorEventBase {\n name: \"render_event\";\n component: string;\n renderCount: number;\n}\n\nexport interface SdkErrorEvent extends AppDoctorEventBase {\n name: \"sdk_error\";\n message: string;\n stack?: string;\n errorContext?: string;\n}\n\nexport type AppDoctorEvent =\n | ScreenLoadEvent\n | NetworkRequestEvent\n | RenderCountEvent\n | SdkErrorEvent;\n\n/** Payload accepted by `AppDoctorClient.emit` (union; avoids `Omit` pitfalls on unions). */\nexport type AppDoctorEmitInput =\n | Omit<ScreenLoadEvent, \"timestamp\" | \"sessionId\">\n | Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\">\n | Omit<RenderCountEvent, \"timestamp\" | \"sessionId\">\n | Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\">;\n\nexport interface Transport {\n send(events: readonly AppDoctorEvent[]): void | Promise<void>;\n flush?: () => void | Promise<void>;\n shutdown?: () => void | Promise<void>;\n}\n\nexport interface AppDoctorConfig {\n enabled?: boolean;\n /** Shortcut to disable all internal work while preserving integration calls */\n noop?: boolean;\n /** 0–1, default 1 */\n sampleRate?: number;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n transports?: Transport[];\n tags?: Record<string, string>;\n /** Add context to every emitted event */\n context?: EventContext;\n /** When true, wraps global fetch (restore on shutdown) */\n instrumentFetch?: boolean;\n /**\n * Redacts/sanitizes network event fields before emission.\n * Returning partial values overrides the computed payload.\n */\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nexport const DEFAULT_FLUSH_INTERVAL_MS = 2000;\nexport const DEFAULT_MAX_QUEUE_SIZE = 200;\n","export function shouldSample(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n","import type {\n AppDoctorConfig,\n AppDoctorEmitInput,\n AppDoctorEvent,\n NetworkRequestEvent,\n SdkErrorEvent,\n Transport,\n} from \"./types.js\";\nimport {\n DEFAULT_FLUSH_INTERVAL_MS,\n DEFAULT_MAX_QUEUE_SIZE,\n} from \"./types.js\";\nimport { shouldSample } from \"./sampling.js\";\n\nfunction now(): number {\n return Date.now();\n}\n\nfunction newSessionId(): string {\n return `${now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class AppDoctorClient {\n readonly sessionId: string;\n private readonly config: Required<\n Pick<\n AppDoctorConfig,\n | \"enabled\"\n | \"noop\"\n | \"sampleRate\"\n | \"flushIntervalMs\"\n | \"maxQueueSize\"\n | \"instrumentFetch\"\n >\n > &\n Pick<AppDoctorConfig, \"tags\" | \"context\" | \"redactNetworkEvent\">;\n private readonly transports: Transport[];\n private queue: AppDoctorEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | undefined;\n private fetchPatched = false;\n private originalFetch: typeof fetch | undefined;\n\n constructor(config: AppDoctorConfig = {}) {\n this.sessionId = newSessionId();\n this.config = {\n enabled: config.enabled ?? true,\n noop: config.noop ?? false,\n sampleRate: config.sampleRate ?? 1,\n flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n maxQueueSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n instrumentFetch: config.instrumentFetch ?? true,\n tags: config.tags,\n context: config.context,\n redactNetworkEvent: config.redactNetworkEvent,\n };\n this.transports = [...(config.transports ?? [])];\n if (this.config.enabled) {\n this.startFlushTimer();\n if (this.config.instrumentFetch && typeof globalThis.fetch === \"function\") {\n this.patchFetch();\n }\n }\n }\n\n updateConfig(partial: Partial<AppDoctorConfig>): void {\n if (partial.enabled !== undefined) {\n (this.config as { enabled: boolean }).enabled = partial.enabled;\n }\n if (partial.noop !== undefined) {\n (this.config as { noop: boolean }).noop = partial.noop;\n }\n if (partial.sampleRate !== undefined) {\n (this.config as { sampleRate: number }).sampleRate = partial.sampleRate;\n }\n if (partial.flushIntervalMs !== undefined) {\n (this.config as { flushIntervalMs: number }).flushIntervalMs =\n partial.flushIntervalMs;\n this.restartFlushTimer();\n }\n if (partial.maxQueueSize !== undefined) {\n (this.config as { maxQueueSize: number }).maxQueueSize =\n partial.maxQueueSize;\n }\n if (partial.tags !== undefined) {\n this.config.tags = partial.tags;\n }\n if (partial.context !== undefined) {\n this.config.context = partial.context;\n }\n if (partial.instrumentFetch !== undefined) {\n const next = partial.instrumentFetch;\n (this.config as { instrumentFetch: boolean }).instrumentFetch = next;\n if (next && !this.fetchPatched) this.patchFetch();\n if (!next && this.fetchPatched) this.restoreFetch();\n }\n if (partial.transports !== undefined) {\n this.transports.length = 0;\n this.transports.push(...partial.transports);\n }\n if (partial.redactNetworkEvent !== undefined) {\n this.config.redactNetworkEvent = partial.redactNetworkEvent;\n }\n }\n\n addTransport(transport: Transport): void {\n this.transports.push(transport);\n }\n\n emit(event: AppDoctorEmitInput): void {\n if (!this.config.enabled) return;\n if (this.config.noop) return;\n if (!shouldSample(this.config.sampleRate)) return;\n\n const { tags: eventTags, ...payload } = event;\n const tags =\n this.config.tags || eventTags\n ? { ...this.config.tags, ...eventTags }\n : undefined;\n\n const full = {\n ...payload,\n timestamp: now(),\n sessionId: this.sessionId,\n tags,\n context: this.config.context,\n } as AppDoctorEvent;\n\n this.enqueue(full);\n }\n\n private enqueue(event: AppDoctorEvent): void {\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift();\n }\n this.queue.push(event);\n }\n\n captureError(message: string, context?: string, err?: unknown): void {\n const stack =\n err instanceof Error && typeof err.stack === \"string\"\n ? err.stack\n : undefined;\n const sdkErr: Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\" | \"tags\"> = {\n name: \"sdk_error\",\n message,\n stack,\n errorContext: context,\n };\n this.emit(sdkErr);\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n await Promise.all(\n this.transports.map(async (t) => {\n try {\n await t.send(batch);\n } catch (e) {\n this.safeInternalError(\"transport.send failed\", e);\n }\n }),\n );\n }\n\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n this.restoreFetch();\n await this.flush();\n await Promise.all(\n this.transports.map(async (t) => {\n if (!t.shutdown) return;\n try {\n await t.shutdown();\n } catch (e) {\n this.safeInternalError(\"transport.shutdown failed\", e);\n }\n }),\n );\n }\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushIntervalMs);\n if (\n typeof this.flushTimer === \"object\" &&\n this.flushTimer &&\n \"unref\" in this.flushTimer &&\n typeof this.flushTimer.unref === \"function\"\n ) {\n this.flushTimer.unref();\n }\n }\n\n private restartFlushTimer(): void {\n if (this.flushTimer) clearInterval(this.flushTimer);\n this.startFlushTimer();\n }\n\n private safeInternalError(msg: string, err: unknown): void {\n const dev =\n typeof __DEV__ !== \"undefined\"\n ? __DEV__\n : typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n if (dev) console.warn(`[AppDoctor] ${msg}`, err);\n }\n\n private patchFetch(): void {\n if (this.fetchPatched) return;\n const g = globalThis as { fetch: typeof fetch };\n this.originalFetch = g.fetch.bind(globalThis);\n const originalFetch = this.originalFetch;\n g.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const start = now();\n let method = \"GET\";\n let url = \"\";\n try {\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.href;\n } else if (typeof Request !== \"undefined\" && input instanceof Request) {\n url = input.url;\n method = input.method;\n }\n if (init?.method) method = init.method;\n } catch {\n /* ignore */\n }\n\n const urlForEvent =\n url ||\n (typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : typeof Request !== \"undefined\" && input instanceof Request\n ? input.url\n : \"[request]\");\n\n try {\n const res = await originalFetch(input, init);\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n status: res.status,\n durationMs,\n success: true,\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n return res;\n } catch (e) {\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n durationMs,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n throw e;\n }\n };\n this.fetchPatched = true;\n }\n\n private restoreFetch(): void {\n if (!this.fetchPatched || !this.originalFetch) return;\n (globalThis as { fetch: typeof fetch }).fetch = this.originalFetch;\n this.fetchPatched = false;\n this.originalFetch = undefined;\n }\n\n private applyNetworkRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n if (!this.config.redactNetworkEvent) return event;\n const redacted = this.config.redactNetworkEvent(event);\n return { ...event, ...redacted };\n }\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface ConsoleTransportOptions {\n label?: string;\n slowScreenThresholdMs?: number;\n slowApiThresholdMs?: number;\n format?: \"pretty\" | \"raw\";\n}\n\nexport function createConsoleTransport(\n options: ConsoleTransportOptions = {},\n): Transport {\n const label = options.label ?? \"AppDoctor\";\n const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1000;\n const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;\n const format = options.format ?? \"pretty\";\n\n function toHint(event: AppDoctorEvent): string | undefined {\n if (\n event.name === \"screen_load\" &&\n event.phase === \"ready\" &&\n event.durationMs >= slowScreenThresholdMs\n ) {\n return `Slow screen \"${event.screen}\" (${event.durationMs}ms). Check expensive effects and repeated renders.`;\n }\n if (event.name === \"api_request\" && event.durationMs >= slowApiThresholdMs) {\n return `Slow API \"${event.method} ${event.url}\" (${event.durationMs}ms). Check server latency, payload size, and retry loops.`;\n }\n return undefined;\n }\n\n function toPrettyLine(event: AppDoctorEvent): string {\n if (event.name === \"screen_load\") {\n return `screen ${event.screen} phase=${event.phase} duration=${event.durationMs}ms`;\n }\n if (event.name === \"api_request\") {\n const status = event.status ?? \"n/a\";\n return `api ${event.method} ${event.url} status=${status} duration=${event.durationMs}ms success=${event.success}`;\n }\n if (event.name === \"render_event\") {\n return `render ${event.component} count=${event.renderCount}`;\n }\n return `sdk_error ${event.message}`;\n }\n\n return {\n send(events: readonly AppDoctorEvent[]): void {\n if (events.length === 0) return;\n for (const event of events) {\n const hint = toHint(event);\n if (hint) {\n console.warn(`[${label}] ${hint}`);\n }\n if (format === \"pretty\") {\n console.log(`[${label}] ${toPrettyLine(event)}`);\n }\n }\n if (format === \"raw\") {\n console.log(`[${label}]`, events);\n }\n },\n };\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface HttpTransportOptions {\n url: string;\n headers?: Record<string, string>;\n maxRetries?: number;\n /** ms */\n initialBackoffMs?: number;\n getExtraBody?: () => Record<string, unknown>;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((r) => setTimeout(r, ms));\n}\n\nexport function createHttpTransport(options: HttpTransportOptions): Transport {\n const maxRetries = options.maxRetries ?? 3;\n const initialBackoffMs = options.initialBackoffMs ?? 500;\n\n return {\n async send(events: readonly AppDoctorEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = {\n events: [...events],\n ...(options.getExtraBody?.() ?? {}),\n };\n let attempt = 0;\n let backoff = initialBackoffMs;\n for (;;) {\n try {\n const res = await fetch(options.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: JSON.stringify(body),\n });\n if (res.ok) return;\n if (res.status >= 400 && res.status < 500 && res.status !== 429) {\n return;\n }\n } catch {\n /* retry */\n }\n attempt += 1;\n if (attempt > maxRetries) return;\n await sleep(backoff);\n backoff *= 2;\n }\n },\n };\n}\n","/**\n * Best-effort active route name from React Navigation state tree.\n * Avoids a hard dependency on `@react-navigation/native` types at runtime.\n */\nexport function getActiveRouteName(state: unknown): string | undefined {\n if (!state || typeof state !== \"object\") return undefined;\n const s = state as {\n index?: number;\n routes?: Array<{ name?: string; state?: unknown }>;\n };\n if (!Array.isArray(s.routes) || typeof s.index !== \"number\") return undefined;\n const route = s.routes[s.index];\n if (!route || typeof route !== \"object\") return undefined;\n if (route.state !== undefined) return getActiveRouteName(route.state);\n return typeof route.name === \"string\" ? route.name : undefined;\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport { getActiveRouteName } from \"./route-name.js\";\n\nexport interface NavigationTimingState {\n lastScreen?: string;\n}\n\n/**\n * Pass the returned listener to `NavigationContainer` as `onStateChange`.\n * Emits `screen_load` when the active route changes and a ready event after the next microtask\n * (approximates first paint/commit after navigation state updates).\n */\nexport function createNavigationStateListener(client: AppDoctorClient): {\n listener: (state: unknown) => void;\n reset: () => void;\n} {\n const timing: NavigationTimingState = {};\n\n return {\n listener(state: unknown) {\n const screen = getActiveRouteName(state);\n if (!screen || screen === timing.lastScreen) return;\n\n timing.lastScreen = screen;\n const startedAt = Date.now();\n\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n\n queueMicrotask(() => {\n if (timing.lastScreen !== screen) return;\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n },\n reset() {\n timing.lastScreen = undefined;\n },\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport type { NetworkRequestEvent } from \"../core/types.js\";\n\n/** Minimal Axios shape to avoid requiring `axios` as a dependency. */\nexport interface AxiosLike {\n interceptors: {\n request: {\n use: (onFulfilled: (value: unknown) => unknown) => number;\n eject: (id: number) => void;\n };\n response: {\n use: (\n onFulfilled: (value: unknown) => unknown,\n onRejected?: (error: unknown) => unknown,\n ) => number;\n eject: (id: number) => void;\n };\n };\n}\n\nexport interface AxiosInstrumentationOptions {\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nfunction getConfig(errorOrResponse: unknown): unknown {\n if (!errorOrResponse || typeof errorOrResponse !== \"object\") return undefined;\n if (\n \"config\" in errorOrResponse &&\n errorOrResponse.config &&\n typeof errorOrResponse.config === \"object\"\n ) {\n return errorOrResponse.config;\n }\n return undefined;\n}\n\nfunction getResponseMeta(response: unknown): {\n status?: number;\n method?: string;\n url?: string;\n} {\n if (!response || typeof response !== \"object\") return {};\n const r = response;\n const status =\n \"status\" in r && typeof r.status === \"number\" ? r.status : undefined;\n const rawConfig = \"config\" in r ? r.config : undefined;\n let method: string | undefined;\n let url: string | undefined;\n if (rawConfig !== null && typeof rawConfig === \"object\") {\n if (\"method\" in rawConfig && typeof rawConfig.method === \"string\") {\n method = rawConfig.method;\n }\n if (\"url\" in rawConfig && typeof rawConfig.url === \"string\") {\n url = rawConfig.url;\n }\n }\n return {\n status,\n method,\n url,\n };\n}\n\n/**\n * Returns an `eject` function to remove interceptors.\n */\nexport function instrumentAxios(\n axios: AxiosLike,\n client: AppDoctorClient,\n options: AxiosInstrumentationOptions = {},\n): () => void {\n function applyRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n const redacted = options.redactNetworkEvent?.(event);\n return redacted ? { ...event, ...redacted } : event;\n }\n\n const starts = new WeakMap<object, number>();\n\n const reqId = axios.interceptors.request.use((config) => {\n if (config !== null && typeof config === \"object\") {\n starts.set(config, Date.now());\n }\n return config;\n });\n\n const resId = axios.interceptors.response.use(\n (response) => {\n const cfg = getConfig(response);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n const { status, method, url } = getResponseMeta(response);\n const event = applyRedaction({\n method: (method ?? \"GET\").toUpperCase(),\n url: url ?? \"\",\n status,\n durationMs: Date.now() - start,\n success: true,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n return response;\n },\n (error: unknown) => {\n const cfg = getConfig(error);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n let method = \"GET\";\n let url = \"\";\n let status: number | undefined;\n let errorMessage = String(error);\n if (error !== null && typeof error === \"object\") {\n if (\"message\" in error && typeof error.message === \"string\") {\n errorMessage = error.message;\n }\n const resp =\n \"response\" in error && error.response !== null &&\n typeof error.response === \"object\"\n ? error.response\n : undefined;\n if (\n resp &&\n \"status\" in resp &&\n typeof resp.status === \"number\"\n ) {\n status = resp.status;\n }\n const errCfg =\n \"config\" in error && error.config !== null &&\n typeof error.config === \"object\"\n ? error.config\n : undefined;\n if (errCfg) {\n if (\"method\" in errCfg && typeof errCfg.method === \"string\") {\n method = errCfg.method.toUpperCase();\n }\n if (\"url\" in errCfg && typeof errCfg.url === \"string\") {\n url = errCfg.url;\n }\n }\n }\n const event = applyRedaction({\n method,\n url,\n status,\n durationMs: Date.now() - start,\n success: false,\n errorMessage,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n const rejectReason =\n error instanceof Error ? error : new Error(String(error));\n return Promise.reject(rejectReason);\n },\n );\n\n return () => {\n axios.interceptors.request.eject(reqId);\n axios.interceptors.response.eject(resId);\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\n\n/**\n * Wraps an async call and emits an `api_request` event with a synthetic URL label.\n */\nexport async function trackApi<T>(\n client: AppDoctorClient,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const start = Date.now();\n try {\n const result = await fn();\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n status: 200,\n durationMs: Date.now() - start,\n success: true,\n });\n return result;\n } catch (e) {\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n durationMs: Date.now() - start,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n throw e;\n }\n}\n","import { createContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\n\nexport const AppDoctorContext = createContext<AppDoctorClient | null>(null);\n","import { useEffect, useRef, type ReactElement, type ReactNode } from \"react\";\nimport { AppDoctorClient } from \"../core/client.js\";\nimport type { AppDoctorConfig } from \"../core/types.js\";\nimport { AppDoctorContext } from \"./context.js\";\n\nexport type AppDoctorProviderProps = AppDoctorConfig & {\n children: ReactNode;\n};\n\nexport function AppDoctorProvider({\n children,\n ...config\n}: AppDoctorProviderProps): ReactElement {\n const clientRef = useRef<AppDoctorClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new AppDoctorClient(config);\n }\n\n const {\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n } = config;\n\n useEffect(() => {\n clientRef.current?.updateConfig({\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n });\n }, [\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n ]);\n\n useEffect(() => {\n return () => {\n void clientRef.current?.shutdown();\n clientRef.current = null;\n };\n }, []);\n\n return (\n <AppDoctorContext.Provider value={clientRef.current}>\n {children}\n </AppDoctorContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport function useAppDoctor(): AppDoctorClient {\n const client = useContext(AppDoctorContext);\n if (!client) {\n throw new Error(\"useAppDoctor must be used within AppDoctorProvider\");\n }\n return client;\n}\n","import { useContext, useEffect } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackScreenOptions {\n client?: AppDoctorClient;\n}\n\n/**\n * Emits `screen_load` lifecycle events on mount and ready.\n */\nexport function useTrackScreen(\n screen: string,\n options: UseTrackScreenOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackScreen requires AppDoctorProvider or options.client\",\n );\n }\n\n useEffect(() => {\n const startedAt = Date.now();\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n queueMicrotask(() => {\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n }, [client, screen]);\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackRenderOptions {\n client?: AppDoctorClient;\n /** Emit every N renders (default 10) to limit noise */\n every?: number;\n}\n\n/**\n * Emits `render_event` periodically when the component re-renders.\n */\nexport function useTrackRender(\n componentName: string,\n options: UseTrackRenderOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackRender requires AppDoctorProvider or options.client\",\n );\n }\n const every = options.every ?? 10;\n const count = useRef(0);\n\n count.current += 1;\n\n useEffect(() => {\n if (count.current % every !== 0) return;\n client.emit({\n name: \"render_event\",\n component: componentName,\n renderCount: count.current,\n });\n });\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -99,11 +99,13 @@ declare class AppDoctorClient {
|
|
|
99
99
|
|
|
100
100
|
declare function shouldSample(rate: number): boolean;
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
interface ConsoleTransportOptions {
|
|
103
103
|
label?: string;
|
|
104
104
|
slowScreenThresholdMs?: number;
|
|
105
105
|
slowApiThresholdMs?: number;
|
|
106
|
-
|
|
106
|
+
format?: "pretty" | "raw";
|
|
107
|
+
}
|
|
108
|
+
declare function createConsoleTransport(options?: ConsoleTransportOptions): Transport;
|
|
107
109
|
|
|
108
110
|
interface HttpTransportOptions {
|
|
109
111
|
url: string;
|
|
@@ -184,4 +186,4 @@ interface UseTrackRenderOptions {
|
|
|
184
186
|
*/
|
|
185
187
|
declare function useTrackRender(componentName: string, options?: UseTrackRenderOptions): void;
|
|
186
188
|
|
|
187
|
-
export { AppDoctorClient, type AppDoctorConfig, AppDoctorContext, type AppDoctorEmitInput, type AppDoctorEvent, type AppDoctorEventName, AppDoctorProvider, type AppDoctorProviderProps, type AxiosInstrumentationOptions, type AxiosLike, type EventContext, type HttpTransportOptions, type NetworkRequestEvent, type RenderCountEvent, type ScreenLoadEvent, type SdkErrorEvent, type Transport, createConsoleTransport, createHttpTransport, createNavigationStateListener, getActiveRouteName, instrumentAxios, shouldSample, trackApi, useAppDoctor, useTrackRender, useTrackScreen };
|
|
189
|
+
export { AppDoctorClient, type AppDoctorConfig, AppDoctorContext, type AppDoctorEmitInput, type AppDoctorEvent, type AppDoctorEventName, AppDoctorProvider, type AppDoctorProviderProps, type AxiosInstrumentationOptions, type AxiosLike, type ConsoleTransportOptions, type EventContext, type HttpTransportOptions, type NetworkRequestEvent, type RenderCountEvent, type ScreenLoadEvent, type SdkErrorEvent, type Transport, createConsoleTransport, createHttpTransport, createNavigationStateListener, getActiveRouteName, instrumentAxios, shouldSample, trackApi, useAppDoctor, useTrackRender, useTrackScreen };
|
package/dist/index.d.ts
CHANGED
|
@@ -99,11 +99,13 @@ declare class AppDoctorClient {
|
|
|
99
99
|
|
|
100
100
|
declare function shouldSample(rate: number): boolean;
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
interface ConsoleTransportOptions {
|
|
103
103
|
label?: string;
|
|
104
104
|
slowScreenThresholdMs?: number;
|
|
105
105
|
slowApiThresholdMs?: number;
|
|
106
|
-
|
|
106
|
+
format?: "pretty" | "raw";
|
|
107
|
+
}
|
|
108
|
+
declare function createConsoleTransport(options?: ConsoleTransportOptions): Transport;
|
|
107
109
|
|
|
108
110
|
interface HttpTransportOptions {
|
|
109
111
|
url: string;
|
|
@@ -184,4 +186,4 @@ interface UseTrackRenderOptions {
|
|
|
184
186
|
*/
|
|
185
187
|
declare function useTrackRender(componentName: string, options?: UseTrackRenderOptions): void;
|
|
186
188
|
|
|
187
|
-
export { AppDoctorClient, type AppDoctorConfig, AppDoctorContext, type AppDoctorEmitInput, type AppDoctorEvent, type AppDoctorEventName, AppDoctorProvider, type AppDoctorProviderProps, type AxiosInstrumentationOptions, type AxiosLike, type EventContext, type HttpTransportOptions, type NetworkRequestEvent, type RenderCountEvent, type ScreenLoadEvent, type SdkErrorEvent, type Transport, createConsoleTransport, createHttpTransport, createNavigationStateListener, getActiveRouteName, instrumentAxios, shouldSample, trackApi, useAppDoctor, useTrackRender, useTrackScreen };
|
|
189
|
+
export { AppDoctorClient, type AppDoctorConfig, AppDoctorContext, type AppDoctorEmitInput, type AppDoctorEvent, type AppDoctorEventName, AppDoctorProvider, type AppDoctorProviderProps, type AxiosInstrumentationOptions, type AxiosLike, type ConsoleTransportOptions, type EventContext, type HttpTransportOptions, type NetworkRequestEvent, type RenderCountEvent, type ScreenLoadEvent, type SdkErrorEvent, type Transport, createConsoleTransport, createHttpTransport, createNavigationStateListener, getActiveRouteName, instrumentAxios, shouldSample, trackApi, useAppDoctor, useTrackRender, useTrackScreen };
|
package/dist/index.js
CHANGED
|
@@ -234,6 +234,7 @@ function createConsoleTransport(options = {}) {
|
|
|
234
234
|
const label = options.label ?? "AppDoctor";
|
|
235
235
|
const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1e3;
|
|
236
236
|
const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;
|
|
237
|
+
const format = options.format ?? "pretty";
|
|
237
238
|
function toHint(event) {
|
|
238
239
|
if (event.name === "screen_load" && event.phase === "ready" && event.durationMs >= slowScreenThresholdMs) {
|
|
239
240
|
return `Slow screen "${event.screen}" (${event.durationMs}ms). Check expensive effects and repeated renders.`;
|
|
@@ -243,6 +244,19 @@ function createConsoleTransport(options = {}) {
|
|
|
243
244
|
}
|
|
244
245
|
return void 0;
|
|
245
246
|
}
|
|
247
|
+
function toPrettyLine(event) {
|
|
248
|
+
if (event.name === "screen_load") {
|
|
249
|
+
return `screen ${event.screen} phase=${event.phase} duration=${event.durationMs}ms`;
|
|
250
|
+
}
|
|
251
|
+
if (event.name === "api_request") {
|
|
252
|
+
const status = event.status ?? "n/a";
|
|
253
|
+
return `api ${event.method} ${event.url} status=${status} duration=${event.durationMs}ms success=${event.success}`;
|
|
254
|
+
}
|
|
255
|
+
if (event.name === "render_event") {
|
|
256
|
+
return `render ${event.component} count=${event.renderCount}`;
|
|
257
|
+
}
|
|
258
|
+
return `sdk_error ${event.message}`;
|
|
259
|
+
}
|
|
246
260
|
return {
|
|
247
261
|
send(events) {
|
|
248
262
|
if (events.length === 0) return;
|
|
@@ -251,8 +265,13 @@ function createConsoleTransport(options = {}) {
|
|
|
251
265
|
if (hint) {
|
|
252
266
|
console.warn(`[${label}] ${hint}`);
|
|
253
267
|
}
|
|
268
|
+
if (format === "pretty") {
|
|
269
|
+
console.log(`[${label}] ${toPrettyLine(event)}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (format === "raw") {
|
|
273
|
+
console.log(`[${label}]`, events);
|
|
254
274
|
}
|
|
255
|
-
console.log(`[${label}]`, events);
|
|
256
275
|
}
|
|
257
276
|
};
|
|
258
277
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/core/sampling.ts","../src/core/client.ts","../src/transports/console-transport.ts","../src/transports/http-transport.ts","../src/navigation/route-name.ts","../src/navigation/create-navigation-listener.ts","../src/network/axios-instrumentation.ts","../src/utils/track-api.ts","../src/provider/context.ts","../src/provider/AppDoctorProvider.tsx","../src/hooks/useAppDoctor.ts","../src/hooks/useTrackScreen.ts","../src/hooks/useTrackRender.ts"],"names":["useContext","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["export type AppDoctorEventName =\n | \"screen_load\"\n | \"api_request\"\n | \"render_event\"\n | \"sdk_error\";\n\nexport interface EventContext {\n route?: string;\n component?: string;\n platform?: string;\n appVersion?: string;\n metadata?: Record<string, string | number | boolean>;\n}\n\nexport interface AppDoctorEventBase {\n name: AppDoctorEventName;\n /** Unix ms */\n timestamp: number;\n sessionId: string;\n tags?: Record<string, string>;\n context?: EventContext;\n}\n\nexport interface ScreenLoadEvent extends AppDoctorEventBase {\n name: \"screen_load\";\n screen: string;\n phase: \"start\" | \"ready\";\n /** Time from navigation intent to ready signal (ms), if known */\n durationMs: number;\n}\n\nexport interface NetworkRequestEvent extends AppDoctorEventBase {\n name: \"api_request\";\n method: string;\n url: string;\n status?: number;\n durationMs: number;\n success: boolean;\n errorMessage?: string;\n}\n\nexport interface RenderCountEvent extends AppDoctorEventBase {\n name: \"render_event\";\n component: string;\n renderCount: number;\n}\n\nexport interface SdkErrorEvent extends AppDoctorEventBase {\n name: \"sdk_error\";\n message: string;\n stack?: string;\n errorContext?: string;\n}\n\nexport type AppDoctorEvent =\n | ScreenLoadEvent\n | NetworkRequestEvent\n | RenderCountEvent\n | SdkErrorEvent;\n\n/** Payload accepted by `AppDoctorClient.emit` (union; avoids `Omit` pitfalls on unions). */\nexport type AppDoctorEmitInput =\n | Omit<ScreenLoadEvent, \"timestamp\" | \"sessionId\">\n | Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\">\n | Omit<RenderCountEvent, \"timestamp\" | \"sessionId\">\n | Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\">;\n\nexport interface Transport {\n send(events: readonly AppDoctorEvent[]): void | Promise<void>;\n flush?: () => void | Promise<void>;\n shutdown?: () => void | Promise<void>;\n}\n\nexport interface AppDoctorConfig {\n enabled?: boolean;\n /** Shortcut to disable all internal work while preserving integration calls */\n noop?: boolean;\n /** 0–1, default 1 */\n sampleRate?: number;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n transports?: Transport[];\n tags?: Record<string, string>;\n /** Add context to every emitted event */\n context?: EventContext;\n /** When true, wraps global fetch (restore on shutdown) */\n instrumentFetch?: boolean;\n /**\n * Redacts/sanitizes network event fields before emission.\n * Returning partial values overrides the computed payload.\n */\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nexport const DEFAULT_FLUSH_INTERVAL_MS = 2000;\nexport const DEFAULT_MAX_QUEUE_SIZE = 200;\n","export function shouldSample(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n","import type {\n AppDoctorConfig,\n AppDoctorEmitInput,\n AppDoctorEvent,\n NetworkRequestEvent,\n SdkErrorEvent,\n Transport,\n} from \"./types.js\";\nimport {\n DEFAULT_FLUSH_INTERVAL_MS,\n DEFAULT_MAX_QUEUE_SIZE,\n} from \"./types.js\";\nimport { shouldSample } from \"./sampling.js\";\n\nfunction now(): number {\n return Date.now();\n}\n\nfunction newSessionId(): string {\n return `${now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class AppDoctorClient {\n readonly sessionId: string;\n private readonly config: Required<\n Pick<\n AppDoctorConfig,\n | \"enabled\"\n | \"noop\"\n | \"sampleRate\"\n | \"flushIntervalMs\"\n | \"maxQueueSize\"\n | \"instrumentFetch\"\n >\n > &\n Pick<AppDoctorConfig, \"tags\" | \"context\" | \"redactNetworkEvent\">;\n private readonly transports: Transport[];\n private queue: AppDoctorEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | undefined;\n private fetchPatched = false;\n private originalFetch: typeof fetch | undefined;\n\n constructor(config: AppDoctorConfig = {}) {\n this.sessionId = newSessionId();\n this.config = {\n enabled: config.enabled ?? true,\n noop: config.noop ?? false,\n sampleRate: config.sampleRate ?? 1,\n flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n maxQueueSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n instrumentFetch: config.instrumentFetch ?? true,\n tags: config.tags,\n context: config.context,\n redactNetworkEvent: config.redactNetworkEvent,\n };\n this.transports = [...(config.transports ?? [])];\n if (this.config.enabled) {\n this.startFlushTimer();\n if (this.config.instrumentFetch && typeof globalThis.fetch === \"function\") {\n this.patchFetch();\n }\n }\n }\n\n updateConfig(partial: Partial<AppDoctorConfig>): void {\n if (partial.enabled !== undefined) {\n (this.config as { enabled: boolean }).enabled = partial.enabled;\n }\n if (partial.noop !== undefined) {\n (this.config as { noop: boolean }).noop = partial.noop;\n }\n if (partial.sampleRate !== undefined) {\n (this.config as { sampleRate: number }).sampleRate = partial.sampleRate;\n }\n if (partial.flushIntervalMs !== undefined) {\n (this.config as { flushIntervalMs: number }).flushIntervalMs =\n partial.flushIntervalMs;\n this.restartFlushTimer();\n }\n if (partial.maxQueueSize !== undefined) {\n (this.config as { maxQueueSize: number }).maxQueueSize =\n partial.maxQueueSize;\n }\n if (partial.tags !== undefined) {\n this.config.tags = partial.tags;\n }\n if (partial.context !== undefined) {\n this.config.context = partial.context;\n }\n if (partial.instrumentFetch !== undefined) {\n const next = partial.instrumentFetch;\n (this.config as { instrumentFetch: boolean }).instrumentFetch = next;\n if (next && !this.fetchPatched) this.patchFetch();\n if (!next && this.fetchPatched) this.restoreFetch();\n }\n if (partial.transports !== undefined) {\n this.transports.length = 0;\n this.transports.push(...partial.transports);\n }\n if (partial.redactNetworkEvent !== undefined) {\n this.config.redactNetworkEvent = partial.redactNetworkEvent;\n }\n }\n\n addTransport(transport: Transport): void {\n this.transports.push(transport);\n }\n\n emit(event: AppDoctorEmitInput): void {\n if (!this.config.enabled) return;\n if (this.config.noop) return;\n if (!shouldSample(this.config.sampleRate)) return;\n\n const { tags: eventTags, ...payload } = event;\n const tags =\n this.config.tags || eventTags\n ? { ...this.config.tags, ...eventTags }\n : undefined;\n\n const full = {\n ...payload,\n timestamp: now(),\n sessionId: this.sessionId,\n tags,\n context: this.config.context,\n } as AppDoctorEvent;\n\n this.enqueue(full);\n }\n\n private enqueue(event: AppDoctorEvent): void {\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift();\n }\n this.queue.push(event);\n }\n\n captureError(message: string, context?: string, err?: unknown): void {\n const stack =\n err instanceof Error && typeof err.stack === \"string\"\n ? err.stack\n : undefined;\n const sdkErr: Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\" | \"tags\"> = {\n name: \"sdk_error\",\n message,\n stack,\n errorContext: context,\n };\n this.emit(sdkErr);\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n await Promise.all(\n this.transports.map(async (t) => {\n try {\n await t.send(batch);\n } catch (e) {\n this.safeInternalError(\"transport.send failed\", e);\n }\n }),\n );\n }\n\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n this.restoreFetch();\n await this.flush();\n await Promise.all(\n this.transports.map(async (t) => {\n if (!t.shutdown) return;\n try {\n await t.shutdown();\n } catch (e) {\n this.safeInternalError(\"transport.shutdown failed\", e);\n }\n }),\n );\n }\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushIntervalMs);\n if (\n typeof this.flushTimer === \"object\" &&\n this.flushTimer &&\n \"unref\" in this.flushTimer &&\n typeof this.flushTimer.unref === \"function\"\n ) {\n this.flushTimer.unref();\n }\n }\n\n private restartFlushTimer(): void {\n if (this.flushTimer) clearInterval(this.flushTimer);\n this.startFlushTimer();\n }\n\n private safeInternalError(msg: string, err: unknown): void {\n const dev =\n typeof __DEV__ !== \"undefined\"\n ? __DEV__\n : typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n if (dev) console.warn(`[AppDoctor] ${msg}`, err);\n }\n\n private patchFetch(): void {\n if (this.fetchPatched) return;\n const g = globalThis as { fetch: typeof fetch };\n this.originalFetch = g.fetch.bind(globalThis);\n const originalFetch = this.originalFetch;\n g.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const start = now();\n let method = \"GET\";\n let url = \"\";\n try {\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.href;\n } else if (typeof Request !== \"undefined\" && input instanceof Request) {\n url = input.url;\n method = input.method;\n }\n if (init?.method) method = init.method;\n } catch {\n /* ignore */\n }\n\n const urlForEvent =\n url ||\n (typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : typeof Request !== \"undefined\" && input instanceof Request\n ? input.url\n : \"[request]\");\n\n try {\n const res = await originalFetch(input, init);\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n status: res.status,\n durationMs,\n success: true,\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n return res;\n } catch (e) {\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n durationMs,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n throw e;\n }\n };\n this.fetchPatched = true;\n }\n\n private restoreFetch(): void {\n if (!this.fetchPatched || !this.originalFetch) return;\n (globalThis as { fetch: typeof fetch }).fetch = this.originalFetch;\n this.fetchPatched = false;\n this.originalFetch = undefined;\n }\n\n private applyNetworkRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n if (!this.config.redactNetworkEvent) return event;\n const redacted = this.config.redactNetworkEvent(event);\n return { ...event, ...redacted };\n }\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport function createConsoleTransport(\n options: {\n label?: string;\n slowScreenThresholdMs?: number;\n slowApiThresholdMs?: number;\n } = {},\n): Transport {\n const label = options.label ?? \"AppDoctor\";\n const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1000;\n const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;\n\n function toHint(event: AppDoctorEvent): string | undefined {\n if (\n event.name === \"screen_load\" &&\n event.phase === \"ready\" &&\n event.durationMs >= slowScreenThresholdMs\n ) {\n return `Slow screen \"${event.screen}\" (${event.durationMs}ms). Check expensive effects and repeated renders.`;\n }\n if (event.name === \"api_request\" && event.durationMs >= slowApiThresholdMs) {\n return `Slow API \"${event.method} ${event.url}\" (${event.durationMs}ms). Check server latency, payload size, and retry loops.`;\n }\n return undefined;\n }\n\n return {\n send(events: readonly AppDoctorEvent[]): void {\n if (events.length === 0) return;\n for (const event of events) {\n const hint = toHint(event);\n if (hint) {\n console.warn(`[${label}] ${hint}`);\n }\n }\n console.log(`[${label}]`, events);\n },\n };\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface HttpTransportOptions {\n url: string;\n headers?: Record<string, string>;\n maxRetries?: number;\n /** ms */\n initialBackoffMs?: number;\n getExtraBody?: () => Record<string, unknown>;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((r) => setTimeout(r, ms));\n}\n\nexport function createHttpTransport(options: HttpTransportOptions): Transport {\n const maxRetries = options.maxRetries ?? 3;\n const initialBackoffMs = options.initialBackoffMs ?? 500;\n\n return {\n async send(events: readonly AppDoctorEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = {\n events: [...events],\n ...(options.getExtraBody?.() ?? {}),\n };\n let attempt = 0;\n let backoff = initialBackoffMs;\n for (;;) {\n try {\n const res = await fetch(options.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: JSON.stringify(body),\n });\n if (res.ok) return;\n if (res.status >= 400 && res.status < 500 && res.status !== 429) {\n return;\n }\n } catch {\n /* retry */\n }\n attempt += 1;\n if (attempt > maxRetries) return;\n await sleep(backoff);\n backoff *= 2;\n }\n },\n };\n}\n","/**\n * Best-effort active route name from React Navigation state tree.\n * Avoids a hard dependency on `@react-navigation/native` types at runtime.\n */\nexport function getActiveRouteName(state: unknown): string | undefined {\n if (!state || typeof state !== \"object\") return undefined;\n const s = state as {\n index?: number;\n routes?: Array<{ name?: string; state?: unknown }>;\n };\n if (!Array.isArray(s.routes) || typeof s.index !== \"number\") return undefined;\n const route = s.routes[s.index];\n if (!route || typeof route !== \"object\") return undefined;\n if (route.state !== undefined) return getActiveRouteName(route.state);\n return typeof route.name === \"string\" ? route.name : undefined;\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport { getActiveRouteName } from \"./route-name.js\";\n\nexport interface NavigationTimingState {\n lastScreen?: string;\n}\n\n/**\n * Pass the returned listener to `NavigationContainer` as `onStateChange`.\n * Emits `screen_load` when the active route changes and a ready event after the next microtask\n * (approximates first paint/commit after navigation state updates).\n */\nexport function createNavigationStateListener(client: AppDoctorClient): {\n listener: (state: unknown) => void;\n reset: () => void;\n} {\n const timing: NavigationTimingState = {};\n\n return {\n listener(state: unknown) {\n const screen = getActiveRouteName(state);\n if (!screen || screen === timing.lastScreen) return;\n\n timing.lastScreen = screen;\n const startedAt = Date.now();\n\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n\n queueMicrotask(() => {\n if (timing.lastScreen !== screen) return;\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n },\n reset() {\n timing.lastScreen = undefined;\n },\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport type { NetworkRequestEvent } from \"../core/types.js\";\n\n/** Minimal Axios shape to avoid requiring `axios` as a dependency. */\nexport interface AxiosLike {\n interceptors: {\n request: {\n use: (onFulfilled: (value: unknown) => unknown) => number;\n eject: (id: number) => void;\n };\n response: {\n use: (\n onFulfilled: (value: unknown) => unknown,\n onRejected?: (error: unknown) => unknown,\n ) => number;\n eject: (id: number) => void;\n };\n };\n}\n\nexport interface AxiosInstrumentationOptions {\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nfunction getConfig(errorOrResponse: unknown): unknown {\n if (!errorOrResponse || typeof errorOrResponse !== \"object\") return undefined;\n if (\n \"config\" in errorOrResponse &&\n errorOrResponse.config &&\n typeof errorOrResponse.config === \"object\"\n ) {\n return errorOrResponse.config;\n }\n return undefined;\n}\n\nfunction getResponseMeta(response: unknown): {\n status?: number;\n method?: string;\n url?: string;\n} {\n if (!response || typeof response !== \"object\") return {};\n const r = response;\n const status =\n \"status\" in r && typeof r.status === \"number\" ? r.status : undefined;\n const rawConfig = \"config\" in r ? r.config : undefined;\n let method: string | undefined;\n let url: string | undefined;\n if (rawConfig !== null && typeof rawConfig === \"object\") {\n if (\"method\" in rawConfig && typeof rawConfig.method === \"string\") {\n method = rawConfig.method;\n }\n if (\"url\" in rawConfig && typeof rawConfig.url === \"string\") {\n url = rawConfig.url;\n }\n }\n return {\n status,\n method,\n url,\n };\n}\n\n/**\n * Returns an `eject` function to remove interceptors.\n */\nexport function instrumentAxios(\n axios: AxiosLike,\n client: AppDoctorClient,\n options: AxiosInstrumentationOptions = {},\n): () => void {\n function applyRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n const redacted = options.redactNetworkEvent?.(event);\n return redacted ? { ...event, ...redacted } : event;\n }\n\n const starts = new WeakMap<object, number>();\n\n const reqId = axios.interceptors.request.use((config) => {\n if (config !== null && typeof config === \"object\") {\n starts.set(config, Date.now());\n }\n return config;\n });\n\n const resId = axios.interceptors.response.use(\n (response) => {\n const cfg = getConfig(response);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n const { status, method, url } = getResponseMeta(response);\n const event = applyRedaction({\n method: (method ?? \"GET\").toUpperCase(),\n url: url ?? \"\",\n status,\n durationMs: Date.now() - start,\n success: true,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n return response;\n },\n (error: unknown) => {\n const cfg = getConfig(error);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n let method = \"GET\";\n let url = \"\";\n let status: number | undefined;\n let errorMessage = String(error);\n if (error !== null && typeof error === \"object\") {\n if (\"message\" in error && typeof error.message === \"string\") {\n errorMessage = error.message;\n }\n const resp =\n \"response\" in error && error.response !== null &&\n typeof error.response === \"object\"\n ? error.response\n : undefined;\n if (\n resp &&\n \"status\" in resp &&\n typeof resp.status === \"number\"\n ) {\n status = resp.status;\n }\n const errCfg =\n \"config\" in error && error.config !== null &&\n typeof error.config === \"object\"\n ? error.config\n : undefined;\n if (errCfg) {\n if (\"method\" in errCfg && typeof errCfg.method === \"string\") {\n method = errCfg.method.toUpperCase();\n }\n if (\"url\" in errCfg && typeof errCfg.url === \"string\") {\n url = errCfg.url;\n }\n }\n }\n const event = applyRedaction({\n method,\n url,\n status,\n durationMs: Date.now() - start,\n success: false,\n errorMessage,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n const rejectReason =\n error instanceof Error ? error : new Error(String(error));\n return Promise.reject(rejectReason);\n },\n );\n\n return () => {\n axios.interceptors.request.eject(reqId);\n axios.interceptors.response.eject(resId);\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\n\n/**\n * Wraps an async call and emits an `api_request` event with a synthetic URL label.\n */\nexport async function trackApi<T>(\n client: AppDoctorClient,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const start = Date.now();\n try {\n const result = await fn();\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n status: 200,\n durationMs: Date.now() - start,\n success: true,\n });\n return result;\n } catch (e) {\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n durationMs: Date.now() - start,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n throw e;\n }\n}\n","import { createContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\n\nexport const AppDoctorContext = createContext<AppDoctorClient | null>(null);\n","import { useEffect, useRef, type ReactElement, type ReactNode } from \"react\";\nimport { AppDoctorClient } from \"../core/client.js\";\nimport type { AppDoctorConfig } from \"../core/types.js\";\nimport { AppDoctorContext } from \"./context.js\";\n\nexport type AppDoctorProviderProps = AppDoctorConfig & {\n children: ReactNode;\n};\n\nexport function AppDoctorProvider({\n children,\n ...config\n}: AppDoctorProviderProps): ReactElement {\n const clientRef = useRef<AppDoctorClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new AppDoctorClient(config);\n }\n\n const {\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n } = config;\n\n useEffect(() => {\n clientRef.current?.updateConfig({\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n });\n }, [\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n ]);\n\n useEffect(() => {\n return () => {\n void clientRef.current?.shutdown();\n clientRef.current = null;\n };\n }, []);\n\n return (\n <AppDoctorContext.Provider value={clientRef.current}>\n {children}\n </AppDoctorContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport function useAppDoctor(): AppDoctorClient {\n const client = useContext(AppDoctorContext);\n if (!client) {\n throw new Error(\"useAppDoctor must be used within AppDoctorProvider\");\n }\n return client;\n}\n","import { useContext, useEffect } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackScreenOptions {\n client?: AppDoctorClient;\n}\n\n/**\n * Emits `screen_load` lifecycle events on mount and ready.\n */\nexport function useTrackScreen(\n screen: string,\n options: UseTrackScreenOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackScreen requires AppDoctorProvider or options.client\",\n );\n }\n\n useEffect(() => {\n const startedAt = Date.now();\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n queueMicrotask(() => {\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n }, [client, screen]);\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackRenderOptions {\n client?: AppDoctorClient;\n /** Emit every N renders (default 10) to limit noise */\n every?: number;\n}\n\n/**\n * Emits `render_event` periodically when the component re-renders.\n */\nexport function useTrackRender(\n componentName: string,\n options: UseTrackRenderOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackRender requires AppDoctorProvider or options.client\",\n );\n }\n const every = options.every ?? 10;\n const count = useRef(0);\n\n count.current += 1;\n\n useEffect(() => {\n if (count.current % every !== 0) return;\n client.emit({\n name: \"render_event\",\n component: componentName,\n renderCount: count.current,\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/core/sampling.ts","../src/core/client.ts","../src/transports/console-transport.ts","../src/transports/http-transport.ts","../src/navigation/route-name.ts","../src/navigation/create-navigation-listener.ts","../src/network/axios-instrumentation.ts","../src/utils/track-api.ts","../src/provider/context.ts","../src/provider/AppDoctorProvider.tsx","../src/hooks/useAppDoctor.ts","../src/hooks/useTrackScreen.ts","../src/hooks/useTrackRender.ts"],"names":["useContext","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["export type AppDoctorEventName =\n | \"screen_load\"\n | \"api_request\"\n | \"render_event\"\n | \"sdk_error\";\n\nexport interface EventContext {\n route?: string;\n component?: string;\n platform?: string;\n appVersion?: string;\n metadata?: Record<string, string | number | boolean>;\n}\n\nexport interface AppDoctorEventBase {\n name: AppDoctorEventName;\n /** Unix ms */\n timestamp: number;\n sessionId: string;\n tags?: Record<string, string>;\n context?: EventContext;\n}\n\nexport interface ScreenLoadEvent extends AppDoctorEventBase {\n name: \"screen_load\";\n screen: string;\n phase: \"start\" | \"ready\";\n /** Time from navigation intent to ready signal (ms), if known */\n durationMs: number;\n}\n\nexport interface NetworkRequestEvent extends AppDoctorEventBase {\n name: \"api_request\";\n method: string;\n url: string;\n status?: number;\n durationMs: number;\n success: boolean;\n errorMessage?: string;\n}\n\nexport interface RenderCountEvent extends AppDoctorEventBase {\n name: \"render_event\";\n component: string;\n renderCount: number;\n}\n\nexport interface SdkErrorEvent extends AppDoctorEventBase {\n name: \"sdk_error\";\n message: string;\n stack?: string;\n errorContext?: string;\n}\n\nexport type AppDoctorEvent =\n | ScreenLoadEvent\n | NetworkRequestEvent\n | RenderCountEvent\n | SdkErrorEvent;\n\n/** Payload accepted by `AppDoctorClient.emit` (union; avoids `Omit` pitfalls on unions). */\nexport type AppDoctorEmitInput =\n | Omit<ScreenLoadEvent, \"timestamp\" | \"sessionId\">\n | Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\">\n | Omit<RenderCountEvent, \"timestamp\" | \"sessionId\">\n | Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\">;\n\nexport interface Transport {\n send(events: readonly AppDoctorEvent[]): void | Promise<void>;\n flush?: () => void | Promise<void>;\n shutdown?: () => void | Promise<void>;\n}\n\nexport interface AppDoctorConfig {\n enabled?: boolean;\n /** Shortcut to disable all internal work while preserving integration calls */\n noop?: boolean;\n /** 0–1, default 1 */\n sampleRate?: number;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n transports?: Transport[];\n tags?: Record<string, string>;\n /** Add context to every emitted event */\n context?: EventContext;\n /** When true, wraps global fetch (restore on shutdown) */\n instrumentFetch?: boolean;\n /**\n * Redacts/sanitizes network event fields before emission.\n * Returning partial values overrides the computed payload.\n */\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nexport const DEFAULT_FLUSH_INTERVAL_MS = 2000;\nexport const DEFAULT_MAX_QUEUE_SIZE = 200;\n","export function shouldSample(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n","import type {\n AppDoctorConfig,\n AppDoctorEmitInput,\n AppDoctorEvent,\n NetworkRequestEvent,\n SdkErrorEvent,\n Transport,\n} from \"./types.js\";\nimport {\n DEFAULT_FLUSH_INTERVAL_MS,\n DEFAULT_MAX_QUEUE_SIZE,\n} from \"./types.js\";\nimport { shouldSample } from \"./sampling.js\";\n\nfunction now(): number {\n return Date.now();\n}\n\nfunction newSessionId(): string {\n return `${now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport class AppDoctorClient {\n readonly sessionId: string;\n private readonly config: Required<\n Pick<\n AppDoctorConfig,\n | \"enabled\"\n | \"noop\"\n | \"sampleRate\"\n | \"flushIntervalMs\"\n | \"maxQueueSize\"\n | \"instrumentFetch\"\n >\n > &\n Pick<AppDoctorConfig, \"tags\" | \"context\" | \"redactNetworkEvent\">;\n private readonly transports: Transport[];\n private queue: AppDoctorEvent[] = [];\n private flushTimer: ReturnType<typeof setInterval> | undefined;\n private fetchPatched = false;\n private originalFetch: typeof fetch | undefined;\n\n constructor(config: AppDoctorConfig = {}) {\n this.sessionId = newSessionId();\n this.config = {\n enabled: config.enabled ?? true,\n noop: config.noop ?? false,\n sampleRate: config.sampleRate ?? 1,\n flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n maxQueueSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n instrumentFetch: config.instrumentFetch ?? true,\n tags: config.tags,\n context: config.context,\n redactNetworkEvent: config.redactNetworkEvent,\n };\n this.transports = [...(config.transports ?? [])];\n if (this.config.enabled) {\n this.startFlushTimer();\n if (this.config.instrumentFetch && typeof globalThis.fetch === \"function\") {\n this.patchFetch();\n }\n }\n }\n\n updateConfig(partial: Partial<AppDoctorConfig>): void {\n if (partial.enabled !== undefined) {\n (this.config as { enabled: boolean }).enabled = partial.enabled;\n }\n if (partial.noop !== undefined) {\n (this.config as { noop: boolean }).noop = partial.noop;\n }\n if (partial.sampleRate !== undefined) {\n (this.config as { sampleRate: number }).sampleRate = partial.sampleRate;\n }\n if (partial.flushIntervalMs !== undefined) {\n (this.config as { flushIntervalMs: number }).flushIntervalMs =\n partial.flushIntervalMs;\n this.restartFlushTimer();\n }\n if (partial.maxQueueSize !== undefined) {\n (this.config as { maxQueueSize: number }).maxQueueSize =\n partial.maxQueueSize;\n }\n if (partial.tags !== undefined) {\n this.config.tags = partial.tags;\n }\n if (partial.context !== undefined) {\n this.config.context = partial.context;\n }\n if (partial.instrumentFetch !== undefined) {\n const next = partial.instrumentFetch;\n (this.config as { instrumentFetch: boolean }).instrumentFetch = next;\n if (next && !this.fetchPatched) this.patchFetch();\n if (!next && this.fetchPatched) this.restoreFetch();\n }\n if (partial.transports !== undefined) {\n this.transports.length = 0;\n this.transports.push(...partial.transports);\n }\n if (partial.redactNetworkEvent !== undefined) {\n this.config.redactNetworkEvent = partial.redactNetworkEvent;\n }\n }\n\n addTransport(transport: Transport): void {\n this.transports.push(transport);\n }\n\n emit(event: AppDoctorEmitInput): void {\n if (!this.config.enabled) return;\n if (this.config.noop) return;\n if (!shouldSample(this.config.sampleRate)) return;\n\n const { tags: eventTags, ...payload } = event;\n const tags =\n this.config.tags || eventTags\n ? { ...this.config.tags, ...eventTags }\n : undefined;\n\n const full = {\n ...payload,\n timestamp: now(),\n sessionId: this.sessionId,\n tags,\n context: this.config.context,\n } as AppDoctorEvent;\n\n this.enqueue(full);\n }\n\n private enqueue(event: AppDoctorEvent): void {\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift();\n }\n this.queue.push(event);\n }\n\n captureError(message: string, context?: string, err?: unknown): void {\n const stack =\n err instanceof Error && typeof err.stack === \"string\"\n ? err.stack\n : undefined;\n const sdkErr: Omit<SdkErrorEvent, \"timestamp\" | \"sessionId\" | \"tags\"> = {\n name: \"sdk_error\",\n message,\n stack,\n errorContext: context,\n };\n this.emit(sdkErr);\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n await Promise.all(\n this.transports.map(async (t) => {\n try {\n await t.send(batch);\n } catch (e) {\n this.safeInternalError(\"transport.send failed\", e);\n }\n }),\n );\n }\n\n async shutdown(): Promise<void> {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n this.restoreFetch();\n await this.flush();\n await Promise.all(\n this.transports.map(async (t) => {\n if (!t.shutdown) return;\n try {\n await t.shutdown();\n } catch (e) {\n this.safeInternalError(\"transport.shutdown failed\", e);\n }\n }),\n );\n }\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.config.flushIntervalMs);\n if (\n typeof this.flushTimer === \"object\" &&\n this.flushTimer &&\n \"unref\" in this.flushTimer &&\n typeof this.flushTimer.unref === \"function\"\n ) {\n this.flushTimer.unref();\n }\n }\n\n private restartFlushTimer(): void {\n if (this.flushTimer) clearInterval(this.flushTimer);\n this.startFlushTimer();\n }\n\n private safeInternalError(msg: string, err: unknown): void {\n const dev =\n typeof __DEV__ !== \"undefined\"\n ? __DEV__\n : typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\";\n if (dev) console.warn(`[AppDoctor] ${msg}`, err);\n }\n\n private patchFetch(): void {\n if (this.fetchPatched) return;\n const g = globalThis as { fetch: typeof fetch };\n this.originalFetch = g.fetch.bind(globalThis);\n const originalFetch = this.originalFetch;\n g.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const start = now();\n let method = \"GET\";\n let url = \"\";\n try {\n if (typeof input === \"string\") {\n url = input;\n } else if (input instanceof URL) {\n url = input.href;\n } else if (typeof Request !== \"undefined\" && input instanceof Request) {\n url = input.url;\n method = input.method;\n }\n if (init?.method) method = init.method;\n } catch {\n /* ignore */\n }\n\n const urlForEvent =\n url ||\n (typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : typeof Request !== \"undefined\" && input instanceof Request\n ? input.url\n : \"[request]\");\n\n try {\n const res = await originalFetch(input, init);\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n status: res.status,\n durationMs,\n success: true,\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n return res;\n } catch (e) {\n const durationMs = now() - start;\n const event = this.applyNetworkRedaction({\n method,\n url: urlForEvent,\n durationMs,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n this.emit({\n name: \"api_request\",\n ...event,\n });\n throw e;\n }\n };\n this.fetchPatched = true;\n }\n\n private restoreFetch(): void {\n if (!this.fetchPatched || !this.originalFetch) return;\n (globalThis as { fetch: typeof fetch }).fetch = this.originalFetch;\n this.fetchPatched = false;\n this.originalFetch = undefined;\n }\n\n private applyNetworkRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n if (!this.config.redactNetworkEvent) return event;\n const redacted = this.config.redactNetworkEvent(event);\n return { ...event, ...redacted };\n }\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface ConsoleTransportOptions {\n label?: string;\n slowScreenThresholdMs?: number;\n slowApiThresholdMs?: number;\n format?: \"pretty\" | \"raw\";\n}\n\nexport function createConsoleTransport(\n options: ConsoleTransportOptions = {},\n): Transport {\n const label = options.label ?? \"AppDoctor\";\n const slowScreenThresholdMs = options.slowScreenThresholdMs ?? 1000;\n const slowApiThresholdMs = options.slowApiThresholdMs ?? 800;\n const format = options.format ?? \"pretty\";\n\n function toHint(event: AppDoctorEvent): string | undefined {\n if (\n event.name === \"screen_load\" &&\n event.phase === \"ready\" &&\n event.durationMs >= slowScreenThresholdMs\n ) {\n return `Slow screen \"${event.screen}\" (${event.durationMs}ms). Check expensive effects and repeated renders.`;\n }\n if (event.name === \"api_request\" && event.durationMs >= slowApiThresholdMs) {\n return `Slow API \"${event.method} ${event.url}\" (${event.durationMs}ms). Check server latency, payload size, and retry loops.`;\n }\n return undefined;\n }\n\n function toPrettyLine(event: AppDoctorEvent): string {\n if (event.name === \"screen_load\") {\n return `screen ${event.screen} phase=${event.phase} duration=${event.durationMs}ms`;\n }\n if (event.name === \"api_request\") {\n const status = event.status ?? \"n/a\";\n return `api ${event.method} ${event.url} status=${status} duration=${event.durationMs}ms success=${event.success}`;\n }\n if (event.name === \"render_event\") {\n return `render ${event.component} count=${event.renderCount}`;\n }\n return `sdk_error ${event.message}`;\n }\n\n return {\n send(events: readonly AppDoctorEvent[]): void {\n if (events.length === 0) return;\n for (const event of events) {\n const hint = toHint(event);\n if (hint) {\n console.warn(`[${label}] ${hint}`);\n }\n if (format === \"pretty\") {\n console.log(`[${label}] ${toPrettyLine(event)}`);\n }\n }\n if (format === \"raw\") {\n console.log(`[${label}]`, events);\n }\n },\n };\n}\n","import type { AppDoctorEvent, Transport } from \"../core/types.js\";\n\nexport interface HttpTransportOptions {\n url: string;\n headers?: Record<string, string>;\n maxRetries?: number;\n /** ms */\n initialBackoffMs?: number;\n getExtraBody?: () => Record<string, unknown>;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((r) => setTimeout(r, ms));\n}\n\nexport function createHttpTransport(options: HttpTransportOptions): Transport {\n const maxRetries = options.maxRetries ?? 3;\n const initialBackoffMs = options.initialBackoffMs ?? 500;\n\n return {\n async send(events: readonly AppDoctorEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = {\n events: [...events],\n ...(options.getExtraBody?.() ?? {}),\n };\n let attempt = 0;\n let backoff = initialBackoffMs;\n for (;;) {\n try {\n const res = await fetch(options.url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: JSON.stringify(body),\n });\n if (res.ok) return;\n if (res.status >= 400 && res.status < 500 && res.status !== 429) {\n return;\n }\n } catch {\n /* retry */\n }\n attempt += 1;\n if (attempt > maxRetries) return;\n await sleep(backoff);\n backoff *= 2;\n }\n },\n };\n}\n","/**\n * Best-effort active route name from React Navigation state tree.\n * Avoids a hard dependency on `@react-navigation/native` types at runtime.\n */\nexport function getActiveRouteName(state: unknown): string | undefined {\n if (!state || typeof state !== \"object\") return undefined;\n const s = state as {\n index?: number;\n routes?: Array<{ name?: string; state?: unknown }>;\n };\n if (!Array.isArray(s.routes) || typeof s.index !== \"number\") return undefined;\n const route = s.routes[s.index];\n if (!route || typeof route !== \"object\") return undefined;\n if (route.state !== undefined) return getActiveRouteName(route.state);\n return typeof route.name === \"string\" ? route.name : undefined;\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport { getActiveRouteName } from \"./route-name.js\";\n\nexport interface NavigationTimingState {\n lastScreen?: string;\n}\n\n/**\n * Pass the returned listener to `NavigationContainer` as `onStateChange`.\n * Emits `screen_load` when the active route changes and a ready event after the next microtask\n * (approximates first paint/commit after navigation state updates).\n */\nexport function createNavigationStateListener(client: AppDoctorClient): {\n listener: (state: unknown) => void;\n reset: () => void;\n} {\n const timing: NavigationTimingState = {};\n\n return {\n listener(state: unknown) {\n const screen = getActiveRouteName(state);\n if (!screen || screen === timing.lastScreen) return;\n\n timing.lastScreen = screen;\n const startedAt = Date.now();\n\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n\n queueMicrotask(() => {\n if (timing.lastScreen !== screen) return;\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n },\n reset() {\n timing.lastScreen = undefined;\n },\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\nimport type { NetworkRequestEvent } from \"../core/types.js\";\n\n/** Minimal Axios shape to avoid requiring `axios` as a dependency. */\nexport interface AxiosLike {\n interceptors: {\n request: {\n use: (onFulfilled: (value: unknown) => unknown) => number;\n eject: (id: number) => void;\n };\n response: {\n use: (\n onFulfilled: (value: unknown) => unknown,\n onRejected?: (error: unknown) => unknown,\n ) => number;\n eject: (id: number) => void;\n };\n };\n}\n\nexport interface AxiosInstrumentationOptions {\n redactNetworkEvent?: (\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ) => Partial<Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">>;\n}\n\nfunction getConfig(errorOrResponse: unknown): unknown {\n if (!errorOrResponse || typeof errorOrResponse !== \"object\") return undefined;\n if (\n \"config\" in errorOrResponse &&\n errorOrResponse.config &&\n typeof errorOrResponse.config === \"object\"\n ) {\n return errorOrResponse.config;\n }\n return undefined;\n}\n\nfunction getResponseMeta(response: unknown): {\n status?: number;\n method?: string;\n url?: string;\n} {\n if (!response || typeof response !== \"object\") return {};\n const r = response;\n const status =\n \"status\" in r && typeof r.status === \"number\" ? r.status : undefined;\n const rawConfig = \"config\" in r ? r.config : undefined;\n let method: string | undefined;\n let url: string | undefined;\n if (rawConfig !== null && typeof rawConfig === \"object\") {\n if (\"method\" in rawConfig && typeof rawConfig.method === \"string\") {\n method = rawConfig.method;\n }\n if (\"url\" in rawConfig && typeof rawConfig.url === \"string\") {\n url = rawConfig.url;\n }\n }\n return {\n status,\n method,\n url,\n };\n}\n\n/**\n * Returns an `eject` function to remove interceptors.\n */\nexport function instrumentAxios(\n axios: AxiosLike,\n client: AppDoctorClient,\n options: AxiosInstrumentationOptions = {},\n): () => void {\n function applyRedaction(\n event: Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\">,\n ): Omit<NetworkRequestEvent, \"timestamp\" | \"sessionId\" | \"name\"> {\n const redacted = options.redactNetworkEvent?.(event);\n return redacted ? { ...event, ...redacted } : event;\n }\n\n const starts = new WeakMap<object, number>();\n\n const reqId = axios.interceptors.request.use((config) => {\n if (config !== null && typeof config === \"object\") {\n starts.set(config, Date.now());\n }\n return config;\n });\n\n const resId = axios.interceptors.response.use(\n (response) => {\n const cfg = getConfig(response);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n const { status, method, url } = getResponseMeta(response);\n const event = applyRedaction({\n method: (method ?? \"GET\").toUpperCase(),\n url: url ?? \"\",\n status,\n durationMs: Date.now() - start,\n success: true,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n return response;\n },\n (error: unknown) => {\n const cfg = getConfig(error);\n if (cfg !== null && typeof cfg === \"object\") {\n const start = starts.get(cfg);\n if (start !== undefined) {\n let method = \"GET\";\n let url = \"\";\n let status: number | undefined;\n let errorMessage = String(error);\n if (error !== null && typeof error === \"object\") {\n if (\"message\" in error && typeof error.message === \"string\") {\n errorMessage = error.message;\n }\n const resp =\n \"response\" in error && error.response !== null &&\n typeof error.response === \"object\"\n ? error.response\n : undefined;\n if (\n resp &&\n \"status\" in resp &&\n typeof resp.status === \"number\"\n ) {\n status = resp.status;\n }\n const errCfg =\n \"config\" in error && error.config !== null &&\n typeof error.config === \"object\"\n ? error.config\n : undefined;\n if (errCfg) {\n if (\"method\" in errCfg && typeof errCfg.method === \"string\") {\n method = errCfg.method.toUpperCase();\n }\n if (\"url\" in errCfg && typeof errCfg.url === \"string\") {\n url = errCfg.url;\n }\n }\n }\n const event = applyRedaction({\n method,\n url,\n status,\n durationMs: Date.now() - start,\n success: false,\n errorMessage,\n });\n client.emit({\n name: \"api_request\",\n ...event,\n });\n starts.delete(cfg);\n }\n }\n const rejectReason =\n error instanceof Error ? error : new Error(String(error));\n return Promise.reject(rejectReason);\n },\n );\n\n return () => {\n axios.interceptors.request.eject(reqId);\n axios.interceptors.response.eject(resId);\n };\n}\n","import type { AppDoctorClient } from \"../core/client.js\";\n\n/**\n * Wraps an async call and emits an `api_request` event with a synthetic URL label.\n */\nexport async function trackApi<T>(\n client: AppDoctorClient,\n label: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const start = Date.now();\n try {\n const result = await fn();\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n status: 200,\n durationMs: Date.now() - start,\n success: true,\n });\n return result;\n } catch (e) {\n client.emit({\n name: \"api_request\",\n method: \"TRACK\",\n url: label,\n durationMs: Date.now() - start,\n success: false,\n errorMessage: e instanceof Error ? e.message : String(e),\n });\n throw e;\n }\n}\n","import { createContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\n\nexport const AppDoctorContext = createContext<AppDoctorClient | null>(null);\n","import { useEffect, useRef, type ReactElement, type ReactNode } from \"react\";\nimport { AppDoctorClient } from \"../core/client.js\";\nimport type { AppDoctorConfig } from \"../core/types.js\";\nimport { AppDoctorContext } from \"./context.js\";\n\nexport type AppDoctorProviderProps = AppDoctorConfig & {\n children: ReactNode;\n};\n\nexport function AppDoctorProvider({\n children,\n ...config\n}: AppDoctorProviderProps): ReactElement {\n const clientRef = useRef<AppDoctorClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new AppDoctorClient(config);\n }\n\n const {\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n } = config;\n\n useEffect(() => {\n clientRef.current?.updateConfig({\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n });\n }, [\n enabled,\n noop,\n sampleRate,\n flushIntervalMs,\n maxQueueSize,\n instrumentFetch,\n tags,\n context,\n transports,\n redactNetworkEvent,\n ]);\n\n useEffect(() => {\n return () => {\n void clientRef.current?.shutdown();\n clientRef.current = null;\n };\n }, []);\n\n return (\n <AppDoctorContext.Provider value={clientRef.current}>\n {children}\n </AppDoctorContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport function useAppDoctor(): AppDoctorClient {\n const client = useContext(AppDoctorContext);\n if (!client) {\n throw new Error(\"useAppDoctor must be used within AppDoctorProvider\");\n }\n return client;\n}\n","import { useContext, useEffect } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackScreenOptions {\n client?: AppDoctorClient;\n}\n\n/**\n * Emits `screen_load` lifecycle events on mount and ready.\n */\nexport function useTrackScreen(\n screen: string,\n options: UseTrackScreenOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackScreen requires AppDoctorProvider or options.client\",\n );\n }\n\n useEffect(() => {\n const startedAt = Date.now();\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"start\",\n durationMs: 0,\n });\n queueMicrotask(() => {\n client.emit({\n name: \"screen_load\",\n screen,\n phase: \"ready\",\n durationMs: Date.now() - startedAt,\n });\n });\n }, [client, screen]);\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport type { AppDoctorClient } from \"../core/client.js\";\nimport { AppDoctorContext } from \"../provider/context.js\";\n\nexport interface UseTrackRenderOptions {\n client?: AppDoctorClient;\n /** Emit every N renders (default 10) to limit noise */\n every?: number;\n}\n\n/**\n * Emits `render_event` periodically when the component re-renders.\n */\nexport function useTrackRender(\n componentName: string,\n options: UseTrackRenderOptions = {},\n): void {\n const fromContext = useContext(AppDoctorContext);\n const client = options.client ?? fromContext;\n if (!client) {\n throw new Error(\n \"useTrackRender requires AppDoctorProvider or options.client\",\n );\n }\n const every = options.every ?? 10;\n const count = useRef(0);\n\n count.current += 1;\n\n useEffect(() => {\n if (count.current % every !== 0) return;\n client.emit({\n name: \"render_event\",\n component: componentName,\n renderCount: count.current,\n });\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appdoctor-rn",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Lightweight React Native performance and observability SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author":
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Kelvin Ajayi",
|
|
8
|
+
"url": "https://github.com/scryptwiz"
|
|
9
|
+
},
|
|
7
10
|
"repository": {
|
|
8
11
|
"type": "git",
|
|
9
12
|
"url": "git+https://github.com/scryptwiz/appdoctor-rn.git"
|