sng-nexus 1.0.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,240 @@
1
+ # sng-nexus
2
+
3
+ React Native client SDK for the Nexus event tracking platform. Collects events from mobile apps and sends them to the Nexus API with automatic offline queuing and retry.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add sng-nexus
9
+
10
+ # Peer dependencies (required)
11
+ pnpm add @react-native-async-storage/async-storage @react-native-community/netinfo
12
+ ```
13
+
14
+ For iOS, run `npx pod-install` after installing.
15
+
16
+ ## Quick Start
17
+
18
+ ```ts
19
+ import { NexusClient } from 'sng-nexus';
20
+
21
+ // Initialize once at app startup
22
+ await NexusClient.init({
23
+ endpoint: 'https://nexus.yourserver.com',
24
+ apiKey: 'mathit:your-secret',
25
+ debug: __DEV__,
26
+ });
27
+
28
+ // Identify user after login
29
+ NexusClient.identify({ userId: 'u_123' });
30
+
31
+ // Track events
32
+ NexusClient.track('purchase', {
33
+ value: 4.99,
34
+ currency: 'USD',
35
+ email: 'user@example.com',
36
+ });
37
+
38
+ // Reset identity on logout
39
+ NexusClient.resetIdentity();
40
+
41
+ // Force flush before app backgrounds
42
+ await NexusClient.flush();
43
+
44
+ // Shut down (cleanup timers and listeners)
45
+ await NexusClient.shutdown();
46
+ ```
47
+
48
+ ## API
49
+
50
+ ### `NexusClient.init(config)`
51
+
52
+ Initializes the SDK. Must be called before any other method. Loads any persisted events from a previous session and starts the flush timer and network listener.
53
+
54
+ **Config options:**
55
+
56
+ | Option | Type | Default | Description |
57
+ |---|---|---|---|
58
+ | `endpoint` | `string` | *required* | Nexus server base URL (e.g., `https://nexus.example.com`) |
59
+ | `apiKey` | `string` | *required* | API key in `appname:secret` format |
60
+ | `flushInterval` | `number` | `30` | Seconds between automatic flush attempts |
61
+ | `maxQueueSize` | `number` | `1000` | Max events stored in offline queue. Oldest dropped when exceeded |
62
+ | `maxRetries` | `number` | `5` | Max retry attempts per event before it's dropped |
63
+ | `debug` | `boolean` | `false` | Log SDK activity to console |
64
+
65
+ ### `NexusClient.identify(identity)`
66
+
67
+ Sets the user identity. Persisted in memory and attached to all subsequent `track()` calls.
68
+
69
+ ```ts
70
+ NexusClient.identify({ userId: 'u_123' });
71
+ NexusClient.identify({ anonymousId: 'anon_456' });
72
+ NexusClient.identify({ userId: 'u_123', anonymousId: 'anon_456' });
73
+ ```
74
+
75
+ ### `NexusClient.track(eventName, properties?, context?)`
76
+
77
+ Queues an event for delivery. Returns immediately (fire-and-forget).
78
+
79
+ - `eventName` — required, 1-256 characters
80
+ - `properties` — optional key-value data (e.g., `{ value: 4.99, currency: 'USD' }`)
81
+ - `context` — optional event context (e.g., `{ locale: 'en_US' }`)
82
+
83
+ The SDK automatically adds:
84
+ - `timestamp` — current Unix time in seconds
85
+ - `context.platform` — `'ios'` or `'android'` via `Platform.OS`
86
+ - `user_id` / `anonymous_id` — from the current identity
87
+
88
+ The server further enriches with `event_id`, `context.ip`, and `context.user_agent`.
89
+
90
+ #### Destination-specific properties
91
+
92
+ To trigger conversions in Meta or Reddit, include these in `properties`:
93
+
94
+ | Property | Type | Purpose |
95
+ |---|---|---|
96
+ | `value` | `number` | Conversion value |
97
+ | `currency` | `string` | ISO currency code (e.g., `USD`) |
98
+ | `email` | `string` | User email (sent raw; server hashes for Meta/Reddit) |
99
+ | `phone` | `string` | User phone (sent raw; server hashes for Meta/Reddit) |
100
+ | `fbc` | `string` | Meta click ID |
101
+ | `fbp` | `string` | Meta browser ID |
102
+
103
+ ### `NexusClient.flush()`
104
+
105
+ Forces an immediate flush of all queued events. Returns a promise that resolves when the flush cycle completes. Skips silently if offline or already flushing.
106
+
107
+ ### `NexusClient.resetIdentity()`
108
+
109
+ Clears the current user identity. Call on logout.
110
+
111
+ ### `NexusClient.shutdown()`
112
+
113
+ Stops the flush timer and network listener, persists the queue, and marks the client as uninitialized. Call when the app is terminating.
114
+
115
+ ## Offline Queue & Retry Behavior
116
+
117
+ Events are persisted to `AsyncStorage` under the key `@nexus:event_queue`. This means events survive app kills, crashes, and reboots.
118
+
119
+ ### Flush triggers
120
+
121
+ A flush is attempted when:
122
+ 1. The flush timer fires (every `flushInterval` seconds)
123
+ 2. The device transitions from offline to online
124
+ 3. `flush()` is called manually
125
+ 4. The queue reaches 10 events (batch threshold)
126
+
127
+ ### Retry strategy
128
+
129
+ | Scenario | Behavior |
130
+ |---|---|
131
+ | **Network offline** | Events stay in queue, flushed on reconnect |
132
+ | **Server 5xx** | Retry with exponential backoff (1s, 2s, 4s, 8s, 16s... capped at 30s) + jitter |
133
+ | **Server 4xx** (validation/auth error) | Event dropped immediately, no retry |
134
+ | **App killed** | Events persist in AsyncStorage, flushed on next `init()` |
135
+ | **Max retries exceeded** | Event dropped from queue |
136
+ | **Queue full** | Oldest events dropped to make room for new ones |
137
+
138
+ ### Backoff formula
139
+
140
+ ```
141
+ delay = min(1000ms * 2^attempt, 30000ms) + random jitter (0-25%)
142
+ ```
143
+
144
+ ## Architecture
145
+
146
+ ```
147
+ src/
148
+ ├── index.ts — Public exports
149
+ ├── client.ts — NexusClient singleton (init, track, identify, flush, shutdown)
150
+ ├── types.ts — TypeScript interfaces (NexusConfig, TrackPayload, etc.)
151
+ ├── queue.ts — AsyncStorage-backed persistent event queue
152
+ ├── network.ts — NetInfo connectivity monitor with reconnect callback
153
+ └── retry.ts — Exponential backoff delay calculator
154
+ ```
155
+
156
+ ### Data flow
157
+
158
+ ```
159
+ track() → EventQueue (in-memory + AsyncStorage)
160
+ ↓ flush trigger
161
+ fetch POST /api/track
162
+ ↓ success
163
+ remove from queue
164
+ ↓ 5xx failure
165
+ increment retry, keep in queue
166
+ ↓ 4xx failure
167
+ drop from queue (bad request)
168
+ ```
169
+
170
+ ## Integration Example
171
+
172
+ ### App.tsx (Expo / bare RN)
173
+
174
+ ```tsx
175
+ import { useEffect } from 'react';
176
+ import { AppState } from 'react-native';
177
+ import { NexusClient } from 'sng-nexus';
178
+
179
+ export default function App() {
180
+ useEffect(() => {
181
+ NexusClient.init({
182
+ endpoint: 'https://nexus.yourserver.com',
183
+ apiKey: 'kidteller:your-secret',
184
+ debug: __DEV__,
185
+ });
186
+
187
+ const sub = AppState.addEventListener('change', (state) => {
188
+ if (state === 'background') {
189
+ NexusClient.flush();
190
+ }
191
+ });
192
+
193
+ return () => {
194
+ sub.remove();
195
+ NexusClient.shutdown();
196
+ };
197
+ }, []);
198
+
199
+ return <MainNavigator />;
200
+ }
201
+ ```
202
+
203
+ ### After login
204
+
205
+ ```ts
206
+ NexusClient.identify({ userId: user.id });
207
+ ```
208
+
209
+ ### Tracking events
210
+
211
+ ```ts
212
+ // Simple event
213
+ NexusClient.track('screen_view', { screen: 'home' });
214
+
215
+ // Purchase with Meta/Reddit conversion data
216
+ NexusClient.track('purchase', {
217
+ value: 4.99,
218
+ currency: 'USD',
219
+ email: user.email,
220
+ });
221
+
222
+ // Custom event with context
223
+ NexusClient.track('level_complete', { level: 5, score: 100 }, { locale: 'en_US' });
224
+ ```
225
+
226
+ ### On logout
227
+
228
+ ```ts
229
+ NexusClient.resetIdentity();
230
+ ```
231
+
232
+ ## Development
233
+
234
+ ```bash
235
+ # From the monorepo root
236
+ pnpm --filter sng-nexus build # Compile TypeScript
237
+ pnpm --filter sng-nexus clean # Remove dist/
238
+ ```
239
+
240
+ The package uses the monorepo's shared `tsconfig.base.json` and builds with `tsc` to `dist/`.
package/client.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { NexusConfig, Identity, EventContext } from './types.js';
2
+ declare class NexusClientImpl {
3
+ private config;
4
+ private queue;
5
+ private network;
6
+ private identity;
7
+ private flushTimer;
8
+ private flushing;
9
+ private initialized;
10
+ init(config: NexusConfig): Promise<void>;
11
+ identify(identity: Identity): void;
12
+ track(eventName: string, properties?: Record<string, unknown>, context?: EventContext): void;
13
+ flush(): Promise<void>;
14
+ resetIdentity(): void;
15
+ shutdown(): Promise<void>;
16
+ private send;
17
+ private log;
18
+ }
19
+ export declare const NexusClient: NexusClientImpl;
20
+ export {};
21
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,WAAW,EAEX,QAAQ,EAIR,YAAY,EACb,MAAM,YAAY,CAAC;AAIpB,cAAM,eAAe;IACnB,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAEtB,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC9C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAKlC,KAAK,CACH,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,YAAY,GACrB,IAAI;IAkCD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6D5B,aAAa,IAAI,IAAI;IAKf,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAWjB,IAAI;IAsBlB,OAAO,CAAC,GAAG;CAKZ;AAED,eAAO,MAAM,WAAW,iBAAwB,CAAC"}
package/client.js ADDED
@@ -0,0 +1,175 @@
1
+ import { Platform } from 'react-native';
2
+ import { EventQueue } from './queue.js';
3
+ import { NetworkMonitor } from './network.js';
4
+ import { getRetryDelay } from './retry.js';
5
+ const FLUSH_BATCH_SIZE = 10;
6
+ class NexusClientImpl {
7
+ config = null;
8
+ queue = null;
9
+ network = null;
10
+ identity = {};
11
+ flushTimer = null;
12
+ flushing = false;
13
+ initialized = false;
14
+ async init(config) {
15
+ if (this.initialized) {
16
+ this.log('Already initialized, call reset() first to re-initialize');
17
+ return;
18
+ }
19
+ this.config = {
20
+ endpoint: config.endpoint.replace(/\/$/, ''),
21
+ apiKey: config.apiKey,
22
+ flushInterval: config.flushInterval ?? 30,
23
+ maxQueueSize: config.maxQueueSize ?? 1000,
24
+ maxRetries: config.maxRetries ?? 5,
25
+ debug: config.debug ?? false,
26
+ };
27
+ this.queue = new EventQueue(this.config.maxQueueSize);
28
+ await this.queue.load();
29
+ this.network = new NetworkMonitor();
30
+ this.network.start(() => {
31
+ this.log('Network reconnected, flushing queue');
32
+ this.flush();
33
+ });
34
+ this.flushTimer = setInterval(() => {
35
+ this.flush();
36
+ }, this.config.flushInterval * 1000);
37
+ this.initialized = true;
38
+ this.log('Initialized');
39
+ // Flush any events persisted from a previous session
40
+ if (this.queue.size > 0) {
41
+ this.log(`Found ${this.queue.size} queued events from previous session`);
42
+ this.flush();
43
+ }
44
+ }
45
+ identify(identity) {
46
+ this.identity = { ...this.identity, ...identity };
47
+ this.log('Identity updated', this.identity);
48
+ }
49
+ track(eventName, properties, context) {
50
+ if (!this.config || !this.queue) {
51
+ console.warn('[Nexus] Not initialized. Call NexusClient.init() first.');
52
+ return;
53
+ }
54
+ const payload = {
55
+ event_name: eventName,
56
+ timestamp: Math.floor(Date.now() / 1000),
57
+ properties,
58
+ context: {
59
+ platform: Platform.OS,
60
+ ...context,
61
+ },
62
+ };
63
+ if (this.identity.userId)
64
+ payload.user_id = this.identity.userId;
65
+ if (this.identity.anonymousId)
66
+ payload.anonymous_id = this.identity.anonymousId;
67
+ const queued = {
68
+ payload,
69
+ retries: 0,
70
+ createdAt: Date.now(),
71
+ };
72
+ this.queue.add(queued);
73
+ this.log('Event queued', eventName);
74
+ // Auto-flush when batch size reached
75
+ if (this.queue.size >= FLUSH_BATCH_SIZE) {
76
+ this.flush();
77
+ }
78
+ }
79
+ async flush() {
80
+ if (!this.config || !this.queue)
81
+ return;
82
+ if (this.flushing)
83
+ return;
84
+ if (this.queue.size === 0)
85
+ return;
86
+ if (this.network && !this.network.isConnected) {
87
+ this.log('Offline, skipping flush');
88
+ return;
89
+ }
90
+ this.flushing = true;
91
+ try {
92
+ const events = this.queue.peek();
93
+ const sent = [];
94
+ const retried = [];
95
+ for (let i = 0; i < events.length; i++) {
96
+ const event = events[i];
97
+ // Skip events with backoff not yet elapsed
98
+ if (event.retries > 0 && event.lastFailedAt) {
99
+ const delay = getRetryDelay(event.retries);
100
+ if (Date.now() - event.lastFailedAt < delay) {
101
+ continue;
102
+ }
103
+ }
104
+ try {
105
+ const response = await this.send(event.payload);
106
+ if (response.success) {
107
+ sent.push(i);
108
+ this.log('Event sent', event.payload.event_name, response.event_id);
109
+ }
110
+ else {
111
+ // Server rejected (400/401) — don't retry
112
+ this.log('Event rejected', event.payload.event_name, response.error);
113
+ sent.push(i);
114
+ }
115
+ }
116
+ catch {
117
+ // Network/server error — retry later
118
+ retried.push(i);
119
+ this.queue.incrementRetry(i);
120
+ this.log('Event send failed, will retry', event.payload.event_name, `attempt ${event.retries + 1}`);
121
+ }
122
+ }
123
+ // Remove sent events in reverse order to preserve indices
124
+ for (let i = sent.length - 1; i >= 0; i--) {
125
+ this.queue.remove(sent[i]);
126
+ }
127
+ this.queue.pruneExpired(this.config.maxRetries);
128
+ await this.queue.persist();
129
+ if (sent.length > 0) {
130
+ this.log(`Flushed ${sent.length} events, ${this.queue.size} remaining`);
131
+ }
132
+ }
133
+ finally {
134
+ this.flushing = false;
135
+ }
136
+ }
137
+ resetIdentity() {
138
+ this.identity = {};
139
+ this.log('Identity reset');
140
+ }
141
+ async shutdown() {
142
+ if (this.flushTimer) {
143
+ clearInterval(this.flushTimer);
144
+ this.flushTimer = null;
145
+ }
146
+ this.network?.stop();
147
+ await this.queue?.persist();
148
+ this.initialized = false;
149
+ this.log('Shut down');
150
+ }
151
+ async send(payload) {
152
+ const url = `${this.config.endpoint}/api/track`;
153
+ const response = await fetch(url, {
154
+ method: 'POST',
155
+ headers: {
156
+ 'Content-Type': 'application/json',
157
+ 'x-api-key': this.config.apiKey,
158
+ },
159
+ body: JSON.stringify(payload),
160
+ });
161
+ const data = (await response.json());
162
+ if (!response.ok && response.status >= 500) {
163
+ // Server error — throw to trigger retry
164
+ throw new Error(`Server error: ${response.status}`);
165
+ }
166
+ return data;
167
+ }
168
+ log(...args) {
169
+ if (this.config?.debug) {
170
+ console.log('[Nexus]', ...args);
171
+ }
172
+ }
173
+ }
174
+ export const NexusClient = new NexusClientImpl();
175
+ //# sourceMappingURL=client.js.map
package/client.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { NexusClient } from './client.js';
2
+ export type { NexusConfig, Identity, EventContext, TrackPayload, TrackResponse, } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC"}
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { NexusClient } from './client.js';
2
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
package/network.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare class NetworkMonitor {
2
+ private unsubscribe;
3
+ private _isConnected;
4
+ get isConnected(): boolean;
5
+ start(onReconnect: () => void): void;
6
+ stop(): void;
7
+ }
8
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"AAEA,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,YAAY,CAAQ;IAE5B,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,KAAK,CAAC,WAAW,EAAE,MAAM,IAAI,GAAG,IAAI;IAWpC,IAAI,IAAI,IAAI;CAIb"}
package/network.js ADDED
@@ -0,0 +1,22 @@
1
+ import NetInfo from '@react-native-community/netinfo';
2
+ export class NetworkMonitor {
3
+ unsubscribe = null;
4
+ _isConnected = true;
5
+ get isConnected() {
6
+ return this._isConnected;
7
+ }
8
+ start(onReconnect) {
9
+ this.unsubscribe = NetInfo.addEventListener((state) => {
10
+ const wasDisconnected = !this._isConnected;
11
+ this._isConnected = state.isConnected ?? true;
12
+ if (wasDisconnected && this._isConnected) {
13
+ onReconnect();
14
+ }
15
+ });
16
+ }
17
+ stop() {
18
+ this.unsubscribe?.();
19
+ this.unsubscribe = null;
20
+ }
21
+ }
22
+ //# sourceMappingURL=network.js.map
package/network.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"AAAA,OAAO,OAA8B,MAAM,iCAAiC,CAAC;AAE7E,MAAM,OAAO,cAAc;IACjB,WAAW,GAAwB,IAAI,CAAC;IACxC,YAAY,GAAG,IAAI,CAAC;IAE5B,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,WAAuB;QAC3B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAmB,EAAE,EAAE;YAClE,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC;YAC3C,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC;YAE9C,IAAI,eAAe,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACzC,WAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "sng-nexus",
3
+ "version": "1.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "peerDependencies": {
18
+ "react-native": ">=0.70.0",
19
+ "@react-native-async-storage/async-storage": ">=1.0.0",
20
+ "@react-native-community/netinfo": ">=9.0.0"
21
+ },
22
+ "peerDependenciesMeta": {
23
+ "@react-native-async-storage/async-storage": {
24
+ "optional": false
25
+ },
26
+ "@react-native-community/netinfo": {
27
+ "optional": false
28
+ }
29
+ }
30
+ }
package/queue.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { QueuedEvent } from './types.js';
2
+ export declare class EventQueue {
3
+ private events;
4
+ private maxSize;
5
+ private dirty;
6
+ constructor(maxSize: number);
7
+ load(): Promise<void>;
8
+ add(event: QueuedEvent): void;
9
+ remove(index: number): void;
10
+ peek(): QueuedEvent[];
11
+ get size(): number;
12
+ incrementRetry(index: number): void;
13
+ /** Remove events that exceeded max retries */
14
+ pruneExpired(maxRetries: number): void;
15
+ persist(): Promise<void>;
16
+ clear(): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=queue.d.ts.map
package/queue.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,MAAM;IAIrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAS7B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,IAAI,WAAW,EAAE;IAIrB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IASnC,8CAA8C;IAC9C,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAQhC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAS7B"}
package/queue.js ADDED
@@ -0,0 +1,78 @@
1
+ import AsyncStorage from '@react-native-async-storage/async-storage';
2
+ const STORAGE_KEY = '@nexus:event_queue';
3
+ export class EventQueue {
4
+ events = [];
5
+ maxSize;
6
+ dirty = false;
7
+ constructor(maxSize) {
8
+ this.maxSize = maxSize;
9
+ }
10
+ async load() {
11
+ try {
12
+ const raw = await AsyncStorage.getItem(STORAGE_KEY);
13
+ if (raw) {
14
+ this.events = JSON.parse(raw);
15
+ }
16
+ }
17
+ catch {
18
+ // Corrupted storage — start fresh
19
+ this.events = [];
20
+ }
21
+ }
22
+ add(event) {
23
+ // Drop oldest events if queue is full
24
+ while (this.events.length >= this.maxSize) {
25
+ this.events.shift();
26
+ }
27
+ this.events.push(event);
28
+ this.dirty = true;
29
+ }
30
+ remove(index) {
31
+ this.events.splice(index, 1);
32
+ this.dirty = true;
33
+ }
34
+ peek() {
35
+ return [...this.events];
36
+ }
37
+ get size() {
38
+ return this.events.length;
39
+ }
40
+ incrementRetry(index) {
41
+ const event = this.events[index];
42
+ if (event) {
43
+ event.retries++;
44
+ event.lastFailedAt = Date.now();
45
+ this.dirty = true;
46
+ }
47
+ }
48
+ /** Remove events that exceeded max retries */
49
+ pruneExpired(maxRetries) {
50
+ const before = this.events.length;
51
+ this.events = this.events.filter((e) => e.retries < maxRetries);
52
+ if (this.events.length !== before) {
53
+ this.dirty = true;
54
+ }
55
+ }
56
+ async persist() {
57
+ if (!this.dirty)
58
+ return;
59
+ try {
60
+ await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(this.events));
61
+ this.dirty = false;
62
+ }
63
+ catch {
64
+ // Storage write failed — events remain in memory, will retry next persist
65
+ }
66
+ }
67
+ async clear() {
68
+ this.events = [];
69
+ this.dirty = false;
70
+ try {
71
+ await AsyncStorage.removeItem(STORAGE_KEY);
72
+ }
73
+ catch {
74
+ // Ignore
75
+ }
76
+ }
77
+ }
78
+ //# sourceMappingURL=queue.js.map
package/queue.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
package/retry.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function getRetryDelay(attempt: number): number;
2
+ //# sourceMappingURL=retry.d.ts.map
package/retry.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKrD"}
package/retry.js ADDED
@@ -0,0 +1,9 @@
1
+ const BASE_DELAY_MS = 1000;
2
+ const MAX_DELAY_MS = 30000;
3
+ export function getRetryDelay(attempt) {
4
+ const delay = Math.min(BASE_DELAY_MS * Math.pow(2, attempt), MAX_DELAY_MS);
5
+ // Add jitter (0-25% of delay) to avoid thundering herd
6
+ const jitter = delay * 0.25 * Math.random();
7
+ return delay + jitter;
8
+ }
9
+ //# sourceMappingURL=retry.js.map
package/retry.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3E,uDAAuD;IACvD,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5C,OAAO,KAAK,GAAG,MAAM,CAAC;AACxB,CAAC"}
package/types.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ export interface NexusConfig {
2
+ /** Base URL of the Nexus server (e.g., https://nexus.example.com) */
3
+ endpoint: string;
4
+ /** API key in format "appname:secret" */
5
+ apiKey: string;
6
+ /** Flush interval in seconds (default: 30) */
7
+ flushInterval?: number;
8
+ /** Max events persisted in offline queue (default: 1000) */
9
+ maxQueueSize?: number;
10
+ /** Max retry attempts per event (default: 5) */
11
+ maxRetries?: number;
12
+ /** Enable debug logging (default: false) */
13
+ debug?: boolean;
14
+ }
15
+ export interface ResolvedConfig {
16
+ endpoint: string;
17
+ apiKey: string;
18
+ flushInterval: number;
19
+ maxQueueSize: number;
20
+ maxRetries: number;
21
+ debug: boolean;
22
+ }
23
+ export interface Identity {
24
+ userId?: string;
25
+ anonymousId?: string;
26
+ }
27
+ export interface EventContext {
28
+ app?: string;
29
+ platform?: string;
30
+ locale?: string;
31
+ [key: string]: unknown;
32
+ }
33
+ export interface TrackPayload {
34
+ event_name: string;
35
+ user_id?: string;
36
+ anonymous_id?: string;
37
+ timestamp?: number;
38
+ properties?: Record<string, unknown>;
39
+ context?: EventContext;
40
+ }
41
+ export interface QueuedEvent {
42
+ payload: TrackPayload;
43
+ retries: number;
44
+ createdAt: number;
45
+ lastFailedAt?: number;
46
+ }
47
+ export interface TrackResponse {
48
+ success: boolean;
49
+ event_id?: string;
50
+ error?: string;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
package/types.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
package/types.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}