@bananalytics/react-native 0.1.0

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.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/context/app.d.ts +12 -0
  4. package/dist/context/app.js +34 -0
  5. package/dist/context/device.d.ts +12 -0
  6. package/dist/context/device.js +38 -0
  7. package/dist/context/session.d.ts +49 -0
  8. package/dist/context/session.js +99 -0
  9. package/dist/core/client.d.ts +112 -0
  10. package/dist/core/client.js +283 -0
  11. package/dist/core/config.d.ts +27 -0
  12. package/dist/core/config.js +41 -0
  13. package/dist/core/errors.d.ts +19 -0
  14. package/dist/core/errors.js +40 -0
  15. package/dist/hooks/BananalyticsProvider.d.ts +22 -0
  16. package/dist/hooks/BananalyticsProvider.js +72 -0
  17. package/dist/hooks/RochadeProvider.d.ts +22 -0
  18. package/dist/hooks/RochadeProvider.js +72 -0
  19. package/dist/hooks/useBananalytics.d.ts +16 -0
  20. package/dist/hooks/useBananalytics.js +26 -0
  21. package/dist/hooks/useRochade.d.ts +16 -0
  22. package/dist/hooks/useRochade.js +26 -0
  23. package/dist/hooks/useTrackScreen.d.ts +14 -0
  24. package/dist/hooks/useTrackScreen.js +24 -0
  25. package/dist/index.d.ts +61 -0
  26. package/dist/index.js +97 -0
  27. package/dist/privacy/consent.d.ts +39 -0
  28. package/dist/privacy/consent.js +57 -0
  29. package/dist/privacy/sanitizer.d.ts +16 -0
  30. package/dist/privacy/sanitizer.js +40 -0
  31. package/dist/tracking/event-builder.d.ts +47 -0
  32. package/dist/tracking/event-builder.js +73 -0
  33. package/dist/tracking/lifecycle-tracker.d.ts +24 -0
  34. package/dist/tracking/lifecycle-tracker.js +51 -0
  35. package/dist/tracking/screen-tracker.d.ts +20 -0
  36. package/dist/tracking/screen-tracker.js +34 -0
  37. package/dist/tracking/user-identity.d.ts +40 -0
  38. package/dist/tracking/user-identity.js +75 -0
  39. package/dist/transport/batcher.d.ts +44 -0
  40. package/dist/transport/batcher.js +91 -0
  41. package/dist/transport/persister.d.ts +49 -0
  42. package/dist/transport/persister.js +148 -0
  43. package/dist/transport/queue.d.ts +41 -0
  44. package/dist/transport/queue.js +67 -0
  45. package/dist/transport/retry.d.ts +15 -0
  46. package/dist/transport/retry.js +52 -0
  47. package/dist/transport/transport.d.ts +23 -0
  48. package/dist/transport/transport.js +51 -0
  49. package/dist/types/common.d.ts +6 -0
  50. package/dist/types/common.js +2 -0
  51. package/dist/types/config.d.ts +25 -0
  52. package/dist/types/config.js +2 -0
  53. package/dist/types/events.d.ts +53 -0
  54. package/dist/types/events.js +2 -0
  55. package/dist/utils/id.d.ts +13 -0
  56. package/dist/utils/id.js +18 -0
  57. package/dist/utils/logger.d.ts +11 -0
  58. package/dist/utils/logger.js +24 -0
  59. package/dist/utils/network.d.ts +7 -0
  60. package/dist/utils/network.js +33 -0
  61. package/dist/utils/time.d.ts +13 -0
  62. package/dist/utils/time.js +17 -0
  63. package/dist/utils/validation.d.ts +26 -0
  64. package/dist/utils/validation.js +60 -0
  65. package/package.json +64 -0
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BananalyticsClient = void 0;
4
+ const config_1 = require("./config");
5
+ const logger_1 = require("../utils/logger");
6
+ const queue_1 = require("../transport/queue");
7
+ const transport_1 = require("../transport/transport");
8
+ const batcher_1 = require("../transport/batcher");
9
+ const persister_1 = require("../transport/persister");
10
+ const event_builder_1 = require("../tracking/event-builder");
11
+ const user_identity_1 = require("../tracking/user-identity");
12
+ const lifecycle_tracker_1 = require("../tracking/lifecycle-tracker");
13
+ const screen_tracker_1 = require("../tracking/screen-tracker");
14
+ const session_1 = require("../context/session");
15
+ const consent_1 = require("../privacy/consent");
16
+ const device_1 = require("../context/device");
17
+ const app_1 = require("../context/app");
18
+ /**
19
+ * Main Bananalytics analytics client.
20
+ * Orchestrates all SDK components: tracking, transport, sessions, and privacy.
21
+ */
22
+ class BananalyticsClient {
23
+ constructor(config, asyncStorage) {
24
+ this.initialized = false;
25
+ this.deviceContext = (0, device_1.getDeviceContext)();
26
+ this.appContext = (0, app_1.getAppContext)();
27
+ this.config = (0, config_1.resolveConfig)(config);
28
+ this.logger = new logger_1.Logger(this.config.debug);
29
+ this.persister = new persister_1.Persister(asyncStorage, this.logger);
30
+ this.queue = new queue_1.EventQueue(this.config.maxQueueSize, this.logger);
31
+ this.transport = new transport_1.Transport(this.config.endpoint, this.config.apiKey, this.logger);
32
+ this.batcher = new batcher_1.Batcher(this.queue, this.transport, this.logger, this.config.flushInterval, this.config.flushAt, this.config.maxRetries);
33
+ this.identity = new user_identity_1.UserIdentity(this.persister, this.logger);
34
+ this.sessionManager = new session_1.SessionManager(this.config.sessionTimeout, this.persister, this.logger);
35
+ this.consent = new consent_1.ConsentManager(this.persister, this.logger);
36
+ this.lifecycleTracker = new lifecycle_tracker_1.LifecycleTracker(this.logger);
37
+ this.screenTracker = new screen_tracker_1.ScreenTracker(this.logger);
38
+ this.eventBuilder = new event_builder_1.EventBuilder({
39
+ getAnonymousId: () => this.identity.getAnonymousId(),
40
+ getUserId: () => this.identity.getUserId(),
41
+ getContext: () => this.getContext(),
42
+ }, this.logger);
43
+ }
44
+ /**
45
+ * Initializes the SDK — loads persisted state and starts auto-tracking.
46
+ * Must be called before any tracking methods.
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * const client = new BananalyticsClient(config, AsyncStorage);
51
+ * await client.initialize();
52
+ * ```
53
+ */
54
+ async initialize() {
55
+ if (this.initialized)
56
+ return;
57
+ try {
58
+ await Promise.all([
59
+ this.identity.initialize(),
60
+ this.sessionManager.initialize(),
61
+ this.consent.initialize(),
62
+ ]);
63
+ // Load persisted queue
64
+ const persistedEvents = await this.persister.loadQueue();
65
+ if (persistedEvents.length > 0) {
66
+ this.queue.unshift(persistedEvents);
67
+ await this.persister.clearQueue();
68
+ this.logger.debug(`Restored ${persistedEvents.length} persisted events`);
69
+ }
70
+ // Set up session callbacks
71
+ this.sessionManager.setCallbacks((session) => {
72
+ this.enqueueEvent(this.eventBuilder.track('$session_start', {
73
+ session_id: session.id,
74
+ }));
75
+ }, (session) => {
76
+ this.enqueueEvent(this.eventBuilder.track('$session_end', {
77
+ session_id: session.id,
78
+ }));
79
+ });
80
+ // Start auto-tracking
81
+ if (this.config.trackAppLifecycle) {
82
+ this.lifecycleTracker.start((eventName, props) => this.track(eventName, props), () => { this.flush().catch(() => { }); }, () => { this.persistQueue(); });
83
+ }
84
+ this.batcher.start();
85
+ this.initialized = true;
86
+ this.logger.debug('Bananalytics SDK initialized');
87
+ }
88
+ catch (err) {
89
+ this.logger.error('Failed to initialize Bananalytics SDK', err);
90
+ }
91
+ }
92
+ /**
93
+ * Tracks a custom event.
94
+ *
95
+ * @param eventName - The name of the event
96
+ * @param properties - Optional event properties
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * client.track('button_clicked', { button: 'signup' });
101
+ * ```
102
+ */
103
+ track(eventName, properties) {
104
+ if (this.consent.isOptedOut())
105
+ return;
106
+ try {
107
+ this.sessionManager.getSession(); // ensure active session
108
+ const payload = this.eventBuilder.track(eventName, properties);
109
+ this.enqueueEvent(payload);
110
+ }
111
+ catch (err) {
112
+ this.logger.error('Failed to track event', err);
113
+ }
114
+ }
115
+ /**
116
+ * Tracks a screen view event.
117
+ *
118
+ * @param screenName - The name of the screen
119
+ * @param properties - Optional screen properties
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * client.screen('HomeScreen');
124
+ * ```
125
+ */
126
+ screen(screenName, properties) {
127
+ if (this.consent.isOptedOut())
128
+ return;
129
+ try {
130
+ this.sessionManager.getSession();
131
+ const payload = this.eventBuilder.screen(screenName, properties);
132
+ this.enqueueEvent(payload);
133
+ }
134
+ catch (err) {
135
+ this.logger.error('Failed to track screen', err);
136
+ }
137
+ }
138
+ /**
139
+ * Identifies the current user.
140
+ *
141
+ * @param userId - The user identifier
142
+ * @param traits - Optional user traits
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * client.identify('user-123', { plan: 'pro' });
147
+ * ```
148
+ */
149
+ identify(userId, traits) {
150
+ if (this.consent.isOptedOut())
151
+ return;
152
+ try {
153
+ this.identity.identify(userId).catch((err) => {
154
+ this.logger.error('Failed to persist identity', err);
155
+ });
156
+ const payload = this.eventBuilder.identify(userId, traits);
157
+ this.enqueueEvent(payload);
158
+ }
159
+ catch (err) {
160
+ this.logger.error('Failed to identify user', err);
161
+ }
162
+ }
163
+ /**
164
+ * Clears user identity, generates a new anonymous ID, and clears the queue.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * client.reset();
169
+ * ```
170
+ */
171
+ reset() {
172
+ try {
173
+ this.identity.reset().catch((err) => {
174
+ this.logger.error('Failed to persist reset', err);
175
+ });
176
+ this.queue.clear();
177
+ this.persister.clearQueue().catch((err) => {
178
+ this.logger.error('Failed to clear persisted queue', err);
179
+ });
180
+ this.logger.debug('Client reset');
181
+ }
182
+ catch (err) {
183
+ this.logger.error('Failed to reset', err);
184
+ }
185
+ }
186
+ /**
187
+ * Opts the user into analytics tracking.
188
+ */
189
+ optIn() {
190
+ this.consent.optIn().catch((err) => {
191
+ this.logger.error('Failed to opt in', err);
192
+ });
193
+ }
194
+ /**
195
+ * Opts the user out of analytics tracking. Stops all event collection.
196
+ */
197
+ optOut() {
198
+ this.consent.optOut().catch((err) => {
199
+ this.logger.error('Failed to opt out', err);
200
+ });
201
+ }
202
+ /**
203
+ * Manually flushes all queued events to the backend.
204
+ *
205
+ * @returns Promise that resolves when the flush completes
206
+ *
207
+ * @example
208
+ * ```ts
209
+ * await client.flush();
210
+ * ```
211
+ */
212
+ async flush() {
213
+ try {
214
+ await this.batcher.flush();
215
+ }
216
+ catch (err) {
217
+ this.logger.error('Manual flush failed', err);
218
+ }
219
+ }
220
+ /**
221
+ * Shuts down the SDK — stops auto-tracking and flushes remaining events.
222
+ */
223
+ async shutdown() {
224
+ this.batcher.stop();
225
+ this.lifecycleTracker.stop();
226
+ await this.flush();
227
+ this.persistQueue();
228
+ }
229
+ /** Returns the screen tracker for React Navigation integration. */
230
+ getScreenTracker() {
231
+ return this.screenTracker;
232
+ }
233
+ getContext() {
234
+ const session = this.sessionManager.getSession();
235
+ return {
236
+ device: this.deviceContext,
237
+ app: this.appContext,
238
+ session: {
239
+ id: session.id,
240
+ startedAt: session.startedAt,
241
+ },
242
+ locale: this.getLocale(),
243
+ timezone: this.getTimezone(),
244
+ };
245
+ }
246
+ enqueueEvent(payload) {
247
+ if (payload) {
248
+ this.batcher.enqueue(payload);
249
+ }
250
+ }
251
+ persistQueue() {
252
+ const events = this.queue.peek();
253
+ if (events.length > 0) {
254
+ this.persister.saveQueue(events).catch((err) => {
255
+ this.logger.error('Failed to persist queue', err);
256
+ });
257
+ }
258
+ }
259
+ getLocale() {
260
+ try {
261
+ // eslint-disable-next-line @typescript-eslint/no-var-requires -- Runtime require
262
+ const { NativeModules, Platform } = require('react-native');
263
+ if (Platform.OS === 'ios') {
264
+ return (NativeModules.SettingsManager?.settings?.AppleLocale ??
265
+ NativeModules.SettingsManager?.settings?.AppleLanguages?.[0] ??
266
+ 'en');
267
+ }
268
+ return NativeModules.I18nManager?.localeIdentifier ?? 'en';
269
+ }
270
+ catch {
271
+ return 'en';
272
+ }
273
+ }
274
+ getTimezone() {
275
+ try {
276
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
277
+ }
278
+ catch {
279
+ return 'UTC';
280
+ }
281
+ }
282
+ }
283
+ exports.BananalyticsClient = BananalyticsClient;
@@ -0,0 +1,27 @@
1
+ import { BananalyticsConfig } from '../types/config';
2
+ /** Resolved configuration with all defaults applied. */
3
+ export interface ResolvedConfig {
4
+ apiKey: string;
5
+ endpoint: string;
6
+ flushInterval: number;
7
+ flushAt: number;
8
+ maxQueueSize: number;
9
+ maxRetries: number;
10
+ debug: boolean;
11
+ trackAppLifecycle: boolean;
12
+ trackScreens: boolean;
13
+ sessionTimeout: number;
14
+ }
15
+ /**
16
+ * Validates and resolves a user-provided config, applying defaults.
17
+ *
18
+ * @param config - User-provided configuration
19
+ * @returns Fully resolved configuration with defaults applied
20
+ * @throws ConfigError if required fields are missing
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const resolved = resolveConfig({ apiKey: 'rk_...', endpoint: 'https://...' });
25
+ * ```
26
+ */
27
+ export declare function resolveConfig(config: BananalyticsConfig): ResolvedConfig;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConfig = resolveConfig;
4
+ const errors_1 = require("./errors");
5
+ const DEFAULT_FLUSH_INTERVAL = 30000;
6
+ const DEFAULT_FLUSH_AT = 20;
7
+ const DEFAULT_MAX_QUEUE_SIZE = 1000;
8
+ const DEFAULT_MAX_RETRIES = 3;
9
+ const DEFAULT_SESSION_TIMEOUT = 1800000; // 30 minutes
10
+ /**
11
+ * Validates and resolves a user-provided config, applying defaults.
12
+ *
13
+ * @param config - User-provided configuration
14
+ * @returns Fully resolved configuration with defaults applied
15
+ * @throws ConfigError if required fields are missing
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const resolved = resolveConfig({ apiKey: 'rk_...', endpoint: 'https://...' });
20
+ * ```
21
+ */
22
+ function resolveConfig(config) {
23
+ if (!config.apiKey) {
24
+ throw new errors_1.ConfigError('apiKey is required');
25
+ }
26
+ if (!config.endpoint) {
27
+ throw new errors_1.ConfigError('endpoint is required');
28
+ }
29
+ return {
30
+ apiKey: config.apiKey,
31
+ endpoint: config.endpoint.replace(/\/+$/, ''),
32
+ flushInterval: config.flushInterval ?? DEFAULT_FLUSH_INTERVAL,
33
+ flushAt: config.flushAt ?? DEFAULT_FLUSH_AT,
34
+ maxQueueSize: config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,
35
+ maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
36
+ debug: config.debug ?? false,
37
+ trackAppLifecycle: config.trackAppLifecycle ?? true,
38
+ trackScreens: config.trackScreens ?? false,
39
+ sessionTimeout: config.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,
40
+ };
41
+ }
@@ -0,0 +1,19 @@
1
+ /** Base error class for all Bananalytics SDK errors. */
2
+ export declare class BananalyticsError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /** Error thrown when a network request fails. */
6
+ export declare class NetworkError extends BananalyticsError {
7
+ readonly statusCode: number | undefined;
8
+ constructor(message: string, statusCode?: number);
9
+ /** Whether the error is retryable (5xx or no status code / network error). */
10
+ get isRetryable(): boolean;
11
+ }
12
+ /** Error thrown for invalid configuration. */
13
+ export declare class ConfigError extends BananalyticsError {
14
+ constructor(message: string);
15
+ }
16
+ /** Error thrown for validation failures. */
17
+ export declare class ValidationError extends BananalyticsError {
18
+ constructor(message: string);
19
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationError = exports.ConfigError = exports.NetworkError = exports.BananalyticsError = void 0;
4
+ /** Base error class for all Bananalytics SDK errors. */
5
+ class BananalyticsError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = 'BananalyticsError';
9
+ }
10
+ }
11
+ exports.BananalyticsError = BananalyticsError;
12
+ /** Error thrown when a network request fails. */
13
+ class NetworkError extends BananalyticsError {
14
+ constructor(message, statusCode) {
15
+ super(message);
16
+ this.name = 'NetworkError';
17
+ this.statusCode = statusCode;
18
+ }
19
+ /** Whether the error is retryable (5xx or no status code / network error). */
20
+ get isRetryable() {
21
+ return this.statusCode === undefined || this.statusCode >= 500;
22
+ }
23
+ }
24
+ exports.NetworkError = NetworkError;
25
+ /** Error thrown for invalid configuration. */
26
+ class ConfigError extends BananalyticsError {
27
+ constructor(message) {
28
+ super(message);
29
+ this.name = 'ConfigError';
30
+ }
31
+ }
32
+ exports.ConfigError = ConfigError;
33
+ /** Error thrown for validation failures. */
34
+ class ValidationError extends BananalyticsError {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = 'ValidationError';
38
+ }
39
+ }
40
+ exports.ValidationError = ValidationError;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { BananalyticsConfig } from '../types/config';
3
+ import { BananalyticsClient } from '../core/client';
4
+ export declare const BananalyticsContext: React.Context<BananalyticsClient | null>;
5
+ interface BananalyticsProviderProps {
6
+ config: BananalyticsConfig;
7
+ children: React.ReactNode;
8
+ }
9
+ /**
10
+ * React context provider that initializes and provides the Bananalytics client.
11
+ *
12
+ * @param props - Provider props with config and children
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <BananalyticsProvider config={{ apiKey: 'rk_...', endpoint: 'https://...' }}>
17
+ * <App />
18
+ * </BananalyticsProvider>
19
+ * ```
20
+ */
21
+ export declare function BananalyticsProvider({ config, children }: BananalyticsProviderProps): JSX.Element;
22
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BananalyticsContext = void 0;
37
+ exports.BananalyticsProvider = BananalyticsProvider;
38
+ const react_1 = __importStar(require("react"));
39
+ const client_1 = require("../core/client");
40
+ // eslint-disable-next-line @typescript-eslint/no-var-requires -- Runtime require for AsyncStorage peer dep
41
+ const AsyncStorage = require('@react-native-async-storage/async-storage').default;
42
+ exports.BananalyticsContext = (0, react_1.createContext)(null);
43
+ /**
44
+ * React context provider that initializes and provides the Bananalytics client.
45
+ *
46
+ * @param props - Provider props with config and children
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <BananalyticsProvider config={{ apiKey: 'rk_...', endpoint: 'https://...' }}>
51
+ * <App />
52
+ * </BananalyticsProvider>
53
+ * ```
54
+ */
55
+ function BananalyticsProvider({ config, children }) {
56
+ const clientRef = (0, react_1.useRef)(null);
57
+ if (!clientRef.current) {
58
+ clientRef.current = new client_1.BananalyticsClient(config, AsyncStorage);
59
+ }
60
+ (0, react_1.useEffect)(() => {
61
+ const client = clientRef.current;
62
+ if (client) {
63
+ client.initialize().catch((err) => {
64
+ console.error('[Bananalytics] Failed to initialize:', err);
65
+ });
66
+ return () => {
67
+ client.shutdown().catch(() => { });
68
+ };
69
+ }
70
+ }, []);
71
+ return (react_1.default.createElement(exports.BananalyticsContext.Provider, { value: clientRef.current }, children));
72
+ }
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { RochadeConfig } from '../types/config';
3
+ import { RochadeClient } from '../core/client';
4
+ export declare const RochadeContext: React.Context<RochadeClient | null>;
5
+ interface RochadeProviderProps {
6
+ config: RochadeConfig;
7
+ children: React.ReactNode;
8
+ }
9
+ /**
10
+ * React context provider that initializes and provides the Rochade client.
11
+ *
12
+ * @param props - Provider props with config and children
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <RochadeProvider config={{ apiKey: 'rk_...', endpoint: 'https://...' }}>
17
+ * <App />
18
+ * </RochadeProvider>
19
+ * ```
20
+ */
21
+ export declare function RochadeProvider({ config, children }: RochadeProviderProps): JSX.Element;
22
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.RochadeContext = void 0;
37
+ exports.RochadeProvider = RochadeProvider;
38
+ const react_1 = __importStar(require("react"));
39
+ const client_1 = require("../core/client");
40
+ // eslint-disable-next-line @typescript-eslint/no-var-requires -- Runtime require for AsyncStorage peer dep
41
+ const AsyncStorage = require('@react-native-async-storage/async-storage').default;
42
+ exports.RochadeContext = (0, react_1.createContext)(null);
43
+ /**
44
+ * React context provider that initializes and provides the Rochade client.
45
+ *
46
+ * @param props - Provider props with config and children
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * <RochadeProvider config={{ apiKey: 'rk_...', endpoint: 'https://...' }}>
51
+ * <App />
52
+ * </RochadeProvider>
53
+ * ```
54
+ */
55
+ function RochadeProvider({ config, children }) {
56
+ const clientRef = (0, react_1.useRef)(null);
57
+ if (!clientRef.current) {
58
+ clientRef.current = new client_1.RochadeClient(config, AsyncStorage);
59
+ }
60
+ (0, react_1.useEffect)(() => {
61
+ const client = clientRef.current;
62
+ if (client) {
63
+ client.initialize().catch((err) => {
64
+ console.error('[Rochade] Failed to initialize:', err);
65
+ });
66
+ return () => {
67
+ client.shutdown().catch(() => { });
68
+ };
69
+ }
70
+ }, []);
71
+ return (react_1.default.createElement(exports.RochadeContext.Provider, { value: clientRef.current }, children));
72
+ }
@@ -0,0 +1,16 @@
1
+ import { BananalyticsClient } from '../core/client';
2
+ /**
3
+ * React hook to access the Bananalytics client instance.
4
+ *
5
+ * @returns The initialized Bananalytics client
6
+ * @throws Error if used outside BananalyticsProvider
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * function MyComponent() {
11
+ * const bananalytics = useBananalytics();
12
+ * bananalytics.track('button_clicked');
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function useBananalytics(): BananalyticsClient;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useBananalytics = useBananalytics;
4
+ const react_1 = require("react");
5
+ const BananalyticsProvider_1 = require("./BananalyticsProvider");
6
+ /**
7
+ * React hook to access the Bananalytics client instance.
8
+ *
9
+ * @returns The initialized Bananalytics client
10
+ * @throws Error if used outside BananalyticsProvider
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * function MyComponent() {
15
+ * const bananalytics = useBananalytics();
16
+ * bananalytics.track('button_clicked');
17
+ * }
18
+ * ```
19
+ */
20
+ function useBananalytics() {
21
+ const client = (0, react_1.useContext)(BananalyticsProvider_1.BananalyticsContext);
22
+ if (!client) {
23
+ throw new Error('useBananalytics must be used within a <BananalyticsProvider>');
24
+ }
25
+ return client;
26
+ }
@@ -0,0 +1,16 @@
1
+ import { RochadeClient } from '../core/client';
2
+ /**
3
+ * React hook to access the Rochade client instance.
4
+ *
5
+ * @returns The initialized Rochade client
6
+ * @throws Error if used outside RochadeProvider
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * function MyComponent() {
11
+ * const rochade = useRochade();
12
+ * rochade.track('button_clicked');
13
+ * }
14
+ * ```
15
+ */
16
+ export declare function useRochade(): RochadeClient;