eventlog-rn 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # eventlog-rn
2
+
3
+ > Functional, type-safe event logging SDK for React Native
4
+
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
6
+ [![Bundle Size](https://img.shields.io/badge/Bundle-11.7KB-success.svg)](https://bundlephobia.com/)
7
+ [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
8
+
9
+ ## What is this?
10
+
11
+ # eventlog-rn
12
+
13
+ Functional, type-safe event logging SDK for React Native.
14
+
15
+ Optimized for **reliability**, **performance**, and **ease of use**.
16
+
17
+ ## Features
18
+
19
+ - **Type-Safe**: Full TypeScript support with generics.
20
+ - **Batched Uploads**: Efficiently queues events to minimize network requests.
21
+ - **Offline Support**: Caches events when offline and syncs when back online.
22
+ - **Session Tracking**: Automatic session management.
23
+ - **Built-in UI**: Inspect logs on-device with the included Viewer component.
24
+
25
+ ## Quick Start
26
+
27
+ ### 1. Install
28
+
29
+ ```bash
30
+ npm install eventlog-rn react-native-mmkv
31
+ ```
32
+
33
+ ### 2. Initialize
34
+
35
+ ```typescript
36
+ import { eventLog } from 'eventlog-rn';
37
+
38
+ // Initialize at app launch based on your config
39
+ eventLog.init({
40
+ // ...
41
+ });
42
+ ```
43
+ Network logging enabled by default!
44
+
45
+ // 2. Log events
46
+ eventLog.screen('HomeScreen');
47
+ eventLog.action('button_clicked', { buttonId: 'checkout' });
48
+
49
+ // 3. Export for debugging
50
+ const result = await eventLog.export({ mode: 'repro' });
51
+
52
+ // 4. View logs (optional)
53
+ import { EventLogViewer, EventLogErrorBoundary } from 'eventlog-rn';
54
+
55
+ // Wrap app for error handling
56
+ <EventLogErrorBoundary>
57
+ <App />
58
+ <EventLogViewer />
59
+ </EventLogErrorBoundary>
60
+ ```
61
+
62
+ ## License
63
+
64
+ MIT
@@ -0,0 +1,206 @@
1
+ export { EventLogViewer, EventLogViewerProps } from './viewer/index.mjs';
2
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
3
+
4
+ /**
5
+ * Type definitions for eventlog-rn/core
6
+ * Strict, immutable types following functional programming principles
7
+ */
8
+ /**
9
+ * Storage adapter interface (AsyncStorage-compatible)
10
+ */
11
+ type StorageAdapter = Readonly<{
12
+ getItem: (key: string) => Promise<string | null>;
13
+ setItem: (key: string, value: string) => Promise<void>;
14
+ removeItem: (key: string) => Promise<void>;
15
+ }>;
16
+ /**
17
+ * Event categories
18
+ */
19
+ type EventCategory = 'screen' | 'action' | 'network' | 'error' | 'log';
20
+ /**
21
+ * Log levels
22
+ */
23
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
24
+ /**
25
+ * Event context (attached to all events)
26
+ */
27
+ type EventContext = Readonly<{
28
+ readonly user?: Readonly<Record<string, unknown>>;
29
+ readonly deviceInfo?: Readonly<Record<string, unknown>>;
30
+ readonly [key: string]: unknown;
31
+ }>;
32
+ /**
33
+ * Immutable event structure
34
+ */
35
+ type Event = Readonly<{
36
+ readonly eventId: string;
37
+ readonly sessionId: string;
38
+ readonly seq: number;
39
+ readonly timestamp: number;
40
+ readonly timestampISO: string;
41
+ readonly timezone: string;
42
+ readonly category: EventCategory;
43
+ readonly payload: unknown;
44
+ readonly context: EventContext;
45
+ }>;
46
+ /**
47
+ * Session information
48
+ */
49
+ type Session = Readonly<{
50
+ readonly sessionId: string;
51
+ readonly sessionStart: number;
52
+ readonly startType: 'cold' | 'warm';
53
+ readonly seq: number;
54
+ readonly lastActivityTime: number;
55
+ }>;
56
+ /**
57
+ * Feature configuration
58
+ */
59
+ type FeatureConfig = Readonly<{
60
+ readonly network?: Readonly<{
61
+ readonly enabled?: boolean;
62
+ readonly interceptFetch?: boolean;
63
+ readonly interceptAxios?: boolean;
64
+ readonly logRequestBody?: boolean;
65
+ readonly logResponseBody?: boolean;
66
+ readonly maxBodySize?: number;
67
+ readonly redactHeaders?: ReadonlyArray<string>;
68
+ }>;
69
+ readonly globalErrors?: Readonly<{
70
+ readonly enabled?: boolean;
71
+ }>;
72
+ }>;
73
+ /**
74
+ * Tracker configuration
75
+ */
76
+ type EventLogConfig = Readonly<{
77
+ readonly autoDetect?: boolean;
78
+ readonly maxEvents?: number;
79
+ readonly maxAgeDays?: number;
80
+ readonly sessionTimeoutMinutes?: number;
81
+ readonly batchWriteDelayMs?: number;
82
+ readonly sanitize?: (event: Event) => Event;
83
+ readonly features?: FeatureConfig;
84
+ }>;
85
+ /**
86
+ * Export options
87
+ */
88
+ type ExportOptions = Readonly<{
89
+ readonly mode: 'repro' | 'full';
90
+ }>;
91
+ /**
92
+ * Network event payload
93
+ */
94
+ type NetworkEventPayload = Readonly<{
95
+ readonly url: string;
96
+ readonly method: string;
97
+ readonly status?: number;
98
+ readonly duration?: number;
99
+ readonly error?: string;
100
+ readonly requestHeaders?: Readonly<Record<string, string>>;
101
+ readonly responseHeaders?: Readonly<Record<string, string>>;
102
+ readonly requestBody?: unknown;
103
+ readonly responseBody?: unknown;
104
+ }>;
105
+ /**
106
+ * Error event payload
107
+ */
108
+ type ErrorEventPayload = Readonly<{
109
+ readonly message: string;
110
+ readonly stack?: string;
111
+ readonly isFatal?: boolean;
112
+ readonly context?: unknown;
113
+ }>;
114
+ /**
115
+ * Result type for operations that can fail
116
+ */
117
+ type Result<T, E = Error> = Readonly<{
118
+ readonly ok: true;
119
+ readonly value: T;
120
+ }> | Readonly<{
121
+ readonly ok: false;
122
+ readonly error: E;
123
+ }>;
124
+ /**
125
+ * Event query for filtering
126
+ */
127
+ type EventQuery = Readonly<{
128
+ readonly category?: ReadonlyArray<EventCategory>;
129
+ readonly timeRange?: Readonly<{
130
+ readonly start: number;
131
+ readonly end: number;
132
+ }>;
133
+ readonly sessionId?: string;
134
+ readonly search?: string;
135
+ readonly limit?: number;
136
+ }>;
137
+ /**
138
+ * EventLog API
139
+ */
140
+ type EventLog = Readonly<{
141
+ readonly init: (config?: Partial<EventLogConfig>) => Promise<Result<void>>;
142
+ readonly isReady: () => boolean;
143
+ readonly screen: (name: string, params?: unknown) => Result<void>;
144
+ readonly action: (name: string, data?: unknown) => Result<void>;
145
+ readonly log: (level: LogLevel, message: string, data?: unknown) => Result<void>;
146
+ readonly error: (error: unknown, context?: unknown) => Result<void>;
147
+ readonly setUser: (user: Readonly<Record<string, unknown>>) => void;
148
+ readonly setContext: (key: string, value: unknown) => void;
149
+ readonly setDeviceInfo: (info: Readonly<Record<string, unknown>>) => void;
150
+ readonly export: (options: ExportOptions) => Promise<Result<string>>;
151
+ readonly clear: () => Promise<Result<void>>;
152
+ readonly getEvents: () => Result<ReadonlyArray<Event>>;
153
+ readonly query: (query: EventQuery) => Result<ReadonlyArray<Event>>;
154
+ readonly network: (payload: NetworkEventPayload) => Result<void>;
155
+ }>;
156
+
157
+ /**
158
+ * Main EventLog API - Functional implementation with closures
159
+ */
160
+
161
+ /**
162
+ * Create EventLog instance (factory function with closure)
163
+ */
164
+ declare const createEventLog: (config?: EventLogConfig) => EventLog;
165
+
166
+ declare const eventLog: Readonly<{
167
+ readonly init: (config?: Partial<EventLogConfig>) => Promise<Result<void>>;
168
+ readonly isReady: () => boolean;
169
+ readonly screen: (name: string, params?: unknown) => Result<void>;
170
+ readonly action: (name: string, data?: unknown) => Result<void>;
171
+ readonly log: (level: LogLevel, message: string, data?: unknown) => Result<void>;
172
+ readonly error: (error: unknown, context?: unknown) => Result<void>;
173
+ readonly setUser: (user: Readonly<Record<string, unknown>>) => void;
174
+ readonly setContext: (key: string, value: unknown) => void;
175
+ readonly setDeviceInfo: (info: Readonly<Record<string, unknown>>) => void;
176
+ readonly export: (options: ExportOptions) => Promise<Result<string>>;
177
+ readonly clear: () => Promise<Result<void>>;
178
+ readonly getEvents: () => Result<ReadonlyArray<Event>>;
179
+ readonly query: (query: EventQuery) => Result<ReadonlyArray<Event>>;
180
+ readonly network: (payload: NetworkEventPayload) => Result<void>;
181
+ }>;
182
+
183
+ type EventLogErrorBoundaryProps = {
184
+ children: ReactNode;
185
+ fallback?: ReactNode;
186
+ onError?: (error: Error, info: ErrorInfo) => void;
187
+ };
188
+ type State = {
189
+ hasError: boolean;
190
+ error: Error | null;
191
+ };
192
+ /**
193
+ * EventLog Error Boundary
194
+ *
195
+ * Catches React render errors in its child component tree.
196
+ * Automatically logs them to the EventLog.
197
+ */
198
+ declare class EventLogErrorBoundary extends Component<EventLogErrorBoundaryProps, State> {
199
+ constructor(props: EventLogErrorBoundaryProps);
200
+ static getDerivedStateFromError(error: Error): State;
201
+ componentDidCatch(error: Error, info: ErrorInfo): void;
202
+ resetError: () => void;
203
+ render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
204
+ }
205
+
206
+ export { type ErrorEventPayload, type Event, type EventCategory, type EventContext, type EventLog, type EventLogConfig, EventLogErrorBoundary, type EventQuery, type ExportOptions, type LogLevel, type NetworkEventPayload, type Result, type Session, type StorageAdapter, createEventLog, eventLog };
@@ -0,0 +1,206 @@
1
+ export { EventLogViewer, EventLogViewerProps } from './viewer/index.js';
2
+ import React, { Component, ReactNode, ErrorInfo } from 'react';
3
+
4
+ /**
5
+ * Type definitions for eventlog-rn/core
6
+ * Strict, immutable types following functional programming principles
7
+ */
8
+ /**
9
+ * Storage adapter interface (AsyncStorage-compatible)
10
+ */
11
+ type StorageAdapter = Readonly<{
12
+ getItem: (key: string) => Promise<string | null>;
13
+ setItem: (key: string, value: string) => Promise<void>;
14
+ removeItem: (key: string) => Promise<void>;
15
+ }>;
16
+ /**
17
+ * Event categories
18
+ */
19
+ type EventCategory = 'screen' | 'action' | 'network' | 'error' | 'log';
20
+ /**
21
+ * Log levels
22
+ */
23
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error';
24
+ /**
25
+ * Event context (attached to all events)
26
+ */
27
+ type EventContext = Readonly<{
28
+ readonly user?: Readonly<Record<string, unknown>>;
29
+ readonly deviceInfo?: Readonly<Record<string, unknown>>;
30
+ readonly [key: string]: unknown;
31
+ }>;
32
+ /**
33
+ * Immutable event structure
34
+ */
35
+ type Event = Readonly<{
36
+ readonly eventId: string;
37
+ readonly sessionId: string;
38
+ readonly seq: number;
39
+ readonly timestamp: number;
40
+ readonly timestampISO: string;
41
+ readonly timezone: string;
42
+ readonly category: EventCategory;
43
+ readonly payload: unknown;
44
+ readonly context: EventContext;
45
+ }>;
46
+ /**
47
+ * Session information
48
+ */
49
+ type Session = Readonly<{
50
+ readonly sessionId: string;
51
+ readonly sessionStart: number;
52
+ readonly startType: 'cold' | 'warm';
53
+ readonly seq: number;
54
+ readonly lastActivityTime: number;
55
+ }>;
56
+ /**
57
+ * Feature configuration
58
+ */
59
+ type FeatureConfig = Readonly<{
60
+ readonly network?: Readonly<{
61
+ readonly enabled?: boolean;
62
+ readonly interceptFetch?: boolean;
63
+ readonly interceptAxios?: boolean;
64
+ readonly logRequestBody?: boolean;
65
+ readonly logResponseBody?: boolean;
66
+ readonly maxBodySize?: number;
67
+ readonly redactHeaders?: ReadonlyArray<string>;
68
+ }>;
69
+ readonly globalErrors?: Readonly<{
70
+ readonly enabled?: boolean;
71
+ }>;
72
+ }>;
73
+ /**
74
+ * Tracker configuration
75
+ */
76
+ type EventLogConfig = Readonly<{
77
+ readonly autoDetect?: boolean;
78
+ readonly maxEvents?: number;
79
+ readonly maxAgeDays?: number;
80
+ readonly sessionTimeoutMinutes?: number;
81
+ readonly batchWriteDelayMs?: number;
82
+ readonly sanitize?: (event: Event) => Event;
83
+ readonly features?: FeatureConfig;
84
+ }>;
85
+ /**
86
+ * Export options
87
+ */
88
+ type ExportOptions = Readonly<{
89
+ readonly mode: 'repro' | 'full';
90
+ }>;
91
+ /**
92
+ * Network event payload
93
+ */
94
+ type NetworkEventPayload = Readonly<{
95
+ readonly url: string;
96
+ readonly method: string;
97
+ readonly status?: number;
98
+ readonly duration?: number;
99
+ readonly error?: string;
100
+ readonly requestHeaders?: Readonly<Record<string, string>>;
101
+ readonly responseHeaders?: Readonly<Record<string, string>>;
102
+ readonly requestBody?: unknown;
103
+ readonly responseBody?: unknown;
104
+ }>;
105
+ /**
106
+ * Error event payload
107
+ */
108
+ type ErrorEventPayload = Readonly<{
109
+ readonly message: string;
110
+ readonly stack?: string;
111
+ readonly isFatal?: boolean;
112
+ readonly context?: unknown;
113
+ }>;
114
+ /**
115
+ * Result type for operations that can fail
116
+ */
117
+ type Result<T, E = Error> = Readonly<{
118
+ readonly ok: true;
119
+ readonly value: T;
120
+ }> | Readonly<{
121
+ readonly ok: false;
122
+ readonly error: E;
123
+ }>;
124
+ /**
125
+ * Event query for filtering
126
+ */
127
+ type EventQuery = Readonly<{
128
+ readonly category?: ReadonlyArray<EventCategory>;
129
+ readonly timeRange?: Readonly<{
130
+ readonly start: number;
131
+ readonly end: number;
132
+ }>;
133
+ readonly sessionId?: string;
134
+ readonly search?: string;
135
+ readonly limit?: number;
136
+ }>;
137
+ /**
138
+ * EventLog API
139
+ */
140
+ type EventLog = Readonly<{
141
+ readonly init: (config?: Partial<EventLogConfig>) => Promise<Result<void>>;
142
+ readonly isReady: () => boolean;
143
+ readonly screen: (name: string, params?: unknown) => Result<void>;
144
+ readonly action: (name: string, data?: unknown) => Result<void>;
145
+ readonly log: (level: LogLevel, message: string, data?: unknown) => Result<void>;
146
+ readonly error: (error: unknown, context?: unknown) => Result<void>;
147
+ readonly setUser: (user: Readonly<Record<string, unknown>>) => void;
148
+ readonly setContext: (key: string, value: unknown) => void;
149
+ readonly setDeviceInfo: (info: Readonly<Record<string, unknown>>) => void;
150
+ readonly export: (options: ExportOptions) => Promise<Result<string>>;
151
+ readonly clear: () => Promise<Result<void>>;
152
+ readonly getEvents: () => Result<ReadonlyArray<Event>>;
153
+ readonly query: (query: EventQuery) => Result<ReadonlyArray<Event>>;
154
+ readonly network: (payload: NetworkEventPayload) => Result<void>;
155
+ }>;
156
+
157
+ /**
158
+ * Main EventLog API - Functional implementation with closures
159
+ */
160
+
161
+ /**
162
+ * Create EventLog instance (factory function with closure)
163
+ */
164
+ declare const createEventLog: (config?: EventLogConfig) => EventLog;
165
+
166
+ declare const eventLog: Readonly<{
167
+ readonly init: (config?: Partial<EventLogConfig>) => Promise<Result<void>>;
168
+ readonly isReady: () => boolean;
169
+ readonly screen: (name: string, params?: unknown) => Result<void>;
170
+ readonly action: (name: string, data?: unknown) => Result<void>;
171
+ readonly log: (level: LogLevel, message: string, data?: unknown) => Result<void>;
172
+ readonly error: (error: unknown, context?: unknown) => Result<void>;
173
+ readonly setUser: (user: Readonly<Record<string, unknown>>) => void;
174
+ readonly setContext: (key: string, value: unknown) => void;
175
+ readonly setDeviceInfo: (info: Readonly<Record<string, unknown>>) => void;
176
+ readonly export: (options: ExportOptions) => Promise<Result<string>>;
177
+ readonly clear: () => Promise<Result<void>>;
178
+ readonly getEvents: () => Result<ReadonlyArray<Event>>;
179
+ readonly query: (query: EventQuery) => Result<ReadonlyArray<Event>>;
180
+ readonly network: (payload: NetworkEventPayload) => Result<void>;
181
+ }>;
182
+
183
+ type EventLogErrorBoundaryProps = {
184
+ children: ReactNode;
185
+ fallback?: ReactNode;
186
+ onError?: (error: Error, info: ErrorInfo) => void;
187
+ };
188
+ type State = {
189
+ hasError: boolean;
190
+ error: Error | null;
191
+ };
192
+ /**
193
+ * EventLog Error Boundary
194
+ *
195
+ * Catches React render errors in its child component tree.
196
+ * Automatically logs them to the EventLog.
197
+ */
198
+ declare class EventLogErrorBoundary extends Component<EventLogErrorBoundaryProps, State> {
199
+ constructor(props: EventLogErrorBoundaryProps);
200
+ static getDerivedStateFromError(error: Error): State;
201
+ componentDidCatch(error: Error, info: ErrorInfo): void;
202
+ resetError: () => void;
203
+ render(): string | number | bigint | boolean | React.JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
204
+ }
205
+
206
+ export { type ErrorEventPayload, type Event, type EventCategory, type EventContext, type EventLog, type EventLogConfig, EventLogErrorBoundary, type EventQuery, type ExportOptions, type LogLevel, type NetworkEventPayload, type Result, type Session, type StorageAdapter, createEventLog, eventLog };