riuve-rn 1.0.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.
- package/LICENSE +21 -0
- package/README.md +848 -0
- package/dist/Riuve.d.ts +91 -0
- package/dist/Riuve.d.ts.map +1 -0
- package/dist/Riuve.js +402 -0
- package/dist/Rive.d.ts +91 -0
- package/dist/Rive.d.ts.map +1 -0
- package/dist/Rive.js +402 -0
- package/dist/adapters/deviceInfo/ExpoDeviceInfo.d.ts +13 -0
- package/dist/adapters/deviceInfo/ExpoDeviceInfo.d.ts.map +1 -0
- package/dist/adapters/deviceInfo/ExpoDeviceInfo.js +91 -0
- package/dist/adapters/deviceInfo/FallbackDeviceInfo.d.ts +13 -0
- package/dist/adapters/deviceInfo/FallbackDeviceInfo.d.ts.map +1 -0
- package/dist/adapters/deviceInfo/FallbackDeviceInfo.js +36 -0
- package/dist/adapters/deviceInfo/NativeDeviceInfo.d.ts +17 -0
- package/dist/adapters/deviceInfo/NativeDeviceInfo.d.ts.map +1 -0
- package/dist/adapters/deviceInfo/NativeDeviceInfo.js +83 -0
- package/dist/adapters/deviceInfo/index.d.ts +14 -0
- package/dist/adapters/deviceInfo/index.d.ts.map +1 -0
- package/dist/adapters/deviceInfo/index.js +38 -0
- package/dist/adapters/deviceInfo/types.d.ts +25 -0
- package/dist/adapters/deviceInfo/types.d.ts.map +1 -0
- package/dist/adapters/deviceInfo/types.js +7 -0
- package/dist/adapters/network/ExpoNetworkManager.d.ts +20 -0
- package/dist/adapters/network/ExpoNetworkManager.d.ts.map +1 -0
- package/dist/adapters/network/ExpoNetworkManager.js +114 -0
- package/dist/adapters/network/FallbackNetworkManager.d.ts +15 -0
- package/dist/adapters/network/FallbackNetworkManager.d.ts.map +1 -0
- package/dist/adapters/network/FallbackNetworkManager.js +27 -0
- package/dist/adapters/network/NativeNetworkManager.d.ts +20 -0
- package/dist/adapters/network/NativeNetworkManager.d.ts.map +1 -0
- package/dist/adapters/network/NativeNetworkManager.js +68 -0
- package/dist/adapters/network/index.d.ts +14 -0
- package/dist/adapters/network/index.d.ts.map +1 -0
- package/dist/adapters/network/index.js +38 -0
- package/dist/adapters/network/types.d.ts +28 -0
- package/dist/adapters/network/types.d.ts.map +1 -0
- package/dist/adapters/network/types.js +7 -0
- package/dist/adapters/utils/moduleDetector.d.ts +17 -0
- package/dist/adapters/utils/moduleDetector.d.ts.map +1 -0
- package/dist/adapters/utils/moduleDetector.js +32 -0
- package/dist/constants.d.ts +41 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +43 -0
- package/dist/core/ApiClient.d.ts +49 -0
- package/dist/core/ApiClient.d.ts.map +1 -0
- package/dist/core/ApiClient.js +184 -0
- package/dist/core/DeviceInfo.d.ts +27 -0
- package/dist/core/DeviceInfo.d.ts.map +1 -0
- package/dist/core/DeviceInfo.js +69 -0
- package/dist/core/EventQueue.d.ts +71 -0
- package/dist/core/EventQueue.d.ts.map +1 -0
- package/dist/core/EventQueue.js +216 -0
- package/dist/core/Storage.d.ts +29 -0
- package/dist/core/Storage.d.ts.map +1 -0
- package/dist/core/Storage.js +88 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/managers/BatchManager.d.ts +50 -0
- package/dist/managers/BatchManager.d.ts.map +1 -0
- package/dist/managers/BatchManager.js +277 -0
- package/dist/managers/IdentityManager.d.ts +47 -0
- package/dist/managers/IdentityManager.d.ts.map +1 -0
- package/dist/managers/IdentityManager.js +135 -0
- package/dist/managers/NetworkManager.d.ts +32 -0
- package/dist/managers/NetworkManager.d.ts.map +1 -0
- package/dist/managers/NetworkManager.js +67 -0
- package/dist/types/api.d.ts +65 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +15 -0
- package/dist/types/config.d.ts +32 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +5 -0
- package/dist/types/events.d.ts +63 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +5 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/storage.d.ts +26 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +5 -0
- package/dist/utils/fetchWithTimeout.d.ts +6 -0
- package/dist/utils/fetchWithTimeout.d.ts.map +1 -0
- package/dist/utils/fetchWithTimeout.js +28 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +39 -0
- package/dist/utils/retry.d.ts +29 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +78 -0
- package/dist/utils/uuid.d.ts +12 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +27 -0
- package/dist/utils/validators.d.ts +32 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +68 -0
- package/package.json +65 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API Client - Handles HTTP requests with retry logic
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ApiClient = void 0;
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
9
|
+
const retry_1 = require("../utils/retry");
|
|
10
|
+
const fetchWithTimeout_1 = require("../utils/fetchWithTimeout");
|
|
11
|
+
class ApiClient {
|
|
12
|
+
constructor(baseUrl, apiKey, maxRetries, retryDelay, timeout = 10000) {
|
|
13
|
+
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.maxRetries = maxRetries;
|
|
16
|
+
this.retryDelay = retryDelay;
|
|
17
|
+
this.timeout = timeout;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Updates the API client configuration
|
|
21
|
+
*/
|
|
22
|
+
updateConfig(baseUrl, apiKey, maxRetries, retryDelay, timeout = 10000) {
|
|
23
|
+
this.baseUrl = baseUrl.replace(/\/$/, '');
|
|
24
|
+
this.apiKey = apiKey;
|
|
25
|
+
this.maxRetries = maxRetries;
|
|
26
|
+
this.retryDelay = retryDelay;
|
|
27
|
+
this.timeout = timeout;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Initialize endpoint
|
|
31
|
+
*/
|
|
32
|
+
async initialize(request) {
|
|
33
|
+
return this.post(constants_1.API_ENDPOINTS.INITIALIZE, {
|
|
34
|
+
...request,
|
|
35
|
+
api_key: this.apiKey,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Identify endpoint
|
|
40
|
+
*/
|
|
41
|
+
async identify(request) {
|
|
42
|
+
return this.post(constants_1.API_ENDPOINTS.IDENTIFY, {
|
|
43
|
+
...request,
|
|
44
|
+
api_key: this.apiKey,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Track endpoint
|
|
49
|
+
*/
|
|
50
|
+
async track(request) {
|
|
51
|
+
return this.post(constants_1.API_ENDPOINTS.TRACK, {
|
|
52
|
+
...request,
|
|
53
|
+
api_key: this.apiKey,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Set FCM token endpoint
|
|
58
|
+
*/
|
|
59
|
+
async setFcmToken(request) {
|
|
60
|
+
return this.post(constants_1.API_ENDPOINTS.FCM_TOKEN, {
|
|
61
|
+
...request,
|
|
62
|
+
api_key: this.apiKey,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Generic POST request with retry logic
|
|
67
|
+
*/
|
|
68
|
+
async post(endpoint, data) {
|
|
69
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
70
|
+
return (0, retry_1.retryWithBackoff)(async () => this.makeRequest(url, data), this.maxRetries, this.retryDelay, (error) => {
|
|
71
|
+
const errorType = this.classifyError(error);
|
|
72
|
+
return (0, retry_1.shouldRetry)(errorType);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Makes the actual HTTP request
|
|
77
|
+
*/
|
|
78
|
+
async makeRequest(url, data) {
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
const endpoint = url.replace(this.baseUrl, '');
|
|
81
|
+
// Extract event count if this is a track request
|
|
82
|
+
const eventCount = data.events ? data.events.length : undefined;
|
|
83
|
+
try {
|
|
84
|
+
logger_1.logger.info(`Making HTTP request: POST ${endpoint}`);
|
|
85
|
+
if (eventCount !== undefined) {
|
|
86
|
+
logger_1.logger.info(` Event count: ${eventCount}`);
|
|
87
|
+
}
|
|
88
|
+
logger_1.logger.info(` URL: ${url}`);
|
|
89
|
+
const response = await (0, fetchWithTimeout_1.fetchWithTimeout)(url, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify(data),
|
|
95
|
+
}, this.timeout);
|
|
96
|
+
const responseTime = Date.now() - startTime;
|
|
97
|
+
// Handle non-OK responses
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
const errorData = await this.parseErrorResponse(response);
|
|
100
|
+
const error = new Error(errorData.message || `HTTP ${response.status}`);
|
|
101
|
+
error.status = response.status;
|
|
102
|
+
error.errorData = errorData;
|
|
103
|
+
logger_1.logger.error(`HTTP request failed: POST ${endpoint}`);
|
|
104
|
+
logger_1.logger.error(` Status: ${response.status} ${response.statusText}`);
|
|
105
|
+
logger_1.logger.error(` Response time: ${responseTime}ms`);
|
|
106
|
+
logger_1.logger.error(` Error: ${errorData.message || errorData.error || 'Unknown error'}`);
|
|
107
|
+
if (errorData.details) {
|
|
108
|
+
logger_1.logger.error(` Details: ${JSON.stringify(errorData.details, null, 2)}`);
|
|
109
|
+
}
|
|
110
|
+
if (eventCount !== undefined) {
|
|
111
|
+
logger_1.logger.error(` Events not processed: ${eventCount} events`);
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
// Parse successful response
|
|
116
|
+
const responseData = await response.json();
|
|
117
|
+
logger_1.logger.info(`HTTP request successful: POST ${endpoint}`);
|
|
118
|
+
logger_1.logger.info(` Status: ${response.status} ${response.statusText}`);
|
|
119
|
+
logger_1.logger.info(` Response time: ${responseTime}ms`);
|
|
120
|
+
if (eventCount !== undefined && responseData.processed !== undefined) {
|
|
121
|
+
logger_1.logger.info(` Events processed: ${responseData.processed}/${eventCount}`);
|
|
122
|
+
}
|
|
123
|
+
return responseData;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
const responseTime = Date.now() - startTime;
|
|
127
|
+
// Only log if it's not already logged above (non-HTTP errors)
|
|
128
|
+
if (!error.status) {
|
|
129
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
130
|
+
logger_1.logger.error(`HTTP request failed: POST ${endpoint} (${responseTime}ms)`);
|
|
131
|
+
logger_1.logger.error(` Error: ${errorMsg}`);
|
|
132
|
+
if (eventCount !== undefined) {
|
|
133
|
+
logger_1.logger.error(` Events not sent: ${eventCount} events`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Parses error response from API
|
|
141
|
+
*/
|
|
142
|
+
async parseErrorResponse(response) {
|
|
143
|
+
try {
|
|
144
|
+
const errorData = await response.json();
|
|
145
|
+
return {
|
|
146
|
+
error: errorData.error || 'Unknown error',
|
|
147
|
+
message: errorData.message,
|
|
148
|
+
code: errorData.code,
|
|
149
|
+
status: response.status,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return {
|
|
154
|
+
error: constants_1.ERROR_MESSAGES.NETWORK_ERROR,
|
|
155
|
+
status: response.status,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Classifies an error into an ErrorType
|
|
161
|
+
*/
|
|
162
|
+
classifyError(error) {
|
|
163
|
+
const { ErrorType } = require('../types');
|
|
164
|
+
// Network errors (no connection)
|
|
165
|
+
if (error.message?.includes('Network request failed') || error.message?.includes('fetch')) {
|
|
166
|
+
return ErrorType.NETWORK_ERROR;
|
|
167
|
+
}
|
|
168
|
+
// Timeout errors
|
|
169
|
+
if (error.message?.includes('timeout')) {
|
|
170
|
+
return ErrorType.TIMEOUT_ERROR;
|
|
171
|
+
}
|
|
172
|
+
// HTTP status-based classification
|
|
173
|
+
if (error.status) {
|
|
174
|
+
if (error.status >= 500) {
|
|
175
|
+
return ErrorType.SERVER_ERROR;
|
|
176
|
+
}
|
|
177
|
+
else if (error.status >= 400) {
|
|
178
|
+
return ErrorType.CLIENT_ERROR;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return ErrorType.UNKNOWN_ERROR;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.ApiClient = ApiClient;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Information Collector
|
|
3
|
+
*
|
|
4
|
+
* Uses the adapter pattern to automatically select the best device info implementation
|
|
5
|
+
* based on available modules (Native > Expo > Fallback)
|
|
6
|
+
*/
|
|
7
|
+
import type { DeviceInfo as DeviceInfoType } from '../types';
|
|
8
|
+
declare class DeviceInfoCollector {
|
|
9
|
+
private adapter;
|
|
10
|
+
private cachedInfo;
|
|
11
|
+
/**
|
|
12
|
+
* Collects device information
|
|
13
|
+
* Uses cached value if available, otherwise collects fresh data
|
|
14
|
+
*/
|
|
15
|
+
collect(): Promise<DeviceInfoType>;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the cached device info without re-collecting
|
|
18
|
+
*/
|
|
19
|
+
get(): DeviceInfoType | null;
|
|
20
|
+
/**
|
|
21
|
+
* Clears the cached device info
|
|
22
|
+
*/
|
|
23
|
+
clearCache(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare const deviceInfoCollector: DeviceInfoCollector;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=DeviceInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeviceInfo.d.ts","sourceRoot":"","sources":["../../src/core/DeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,UAAU,CAAC;AAI7D,cAAM,mBAAmB;IACvB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,UAAU,CAA+B;IAEjD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IA0CxC;;OAEG;IACH,GAAG,IAAI,cAAc,GAAG,IAAI;IAI5B;;OAEG;IACH,UAAU,IAAI,IAAI;CAGnB;AAED,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Device Information Collector
|
|
4
|
+
*
|
|
5
|
+
* Uses the adapter pattern to automatically select the best device info implementation
|
|
6
|
+
* based on available modules (Native > Expo > Fallback)
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.deviceInfoCollector = void 0;
|
|
10
|
+
const deviceInfo_1 = require("../adapters/deviceInfo");
|
|
11
|
+
const logger_1 = require("../utils/logger");
|
|
12
|
+
const Storage_1 = require("./Storage");
|
|
13
|
+
class DeviceInfoCollector {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.adapter = (0, deviceInfo_1.getDeviceInfoAdapter)();
|
|
16
|
+
this.cachedInfo = null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Collects device information
|
|
20
|
+
* Uses cached value if available, otherwise collects fresh data
|
|
21
|
+
*/
|
|
22
|
+
async collect() {
|
|
23
|
+
// Return cached info if available
|
|
24
|
+
if (this.cachedInfo) {
|
|
25
|
+
return this.cachedInfo;
|
|
26
|
+
}
|
|
27
|
+
// Try to load from storage
|
|
28
|
+
const storedInfo = await Storage_1.storage.get('DEVICE_INFO');
|
|
29
|
+
if (storedInfo) {
|
|
30
|
+
this.cachedInfo = storedInfo;
|
|
31
|
+
return storedInfo;
|
|
32
|
+
}
|
|
33
|
+
// Collect fresh device info using adapter
|
|
34
|
+
logger_1.logger.debug('Collecting device information...');
|
|
35
|
+
try {
|
|
36
|
+
const deviceInfo = await this.adapter.collect();
|
|
37
|
+
// Cache and store the info
|
|
38
|
+
this.cachedInfo = deviceInfo;
|
|
39
|
+
await Storage_1.storage.set('DEVICE_INFO', deviceInfo);
|
|
40
|
+
logger_1.logger.debug('Device info collected');
|
|
41
|
+
return deviceInfo;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
logger_1.logger.error('Failed to collect device info:', error);
|
|
45
|
+
// Return fallback device info
|
|
46
|
+
const fallbackInfo = {
|
|
47
|
+
os_version: 'unknown',
|
|
48
|
+
device_model: 'unknown',
|
|
49
|
+
app_version: '1.0.0',
|
|
50
|
+
locale: 'en-US',
|
|
51
|
+
platform: 'android',
|
|
52
|
+
};
|
|
53
|
+
return fallbackInfo;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Gets the cached device info without re-collecting
|
|
58
|
+
*/
|
|
59
|
+
get() {
|
|
60
|
+
return this.cachedInfo;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Clears the cached device info
|
|
64
|
+
*/
|
|
65
|
+
clearCache() {
|
|
66
|
+
this.cachedInfo = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.deviceInfoCollector = new DeviceInfoCollector();
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Queue - Manages batching logic
|
|
3
|
+
*/
|
|
4
|
+
import type { Event } from '../types';
|
|
5
|
+
export type FlushCallback = (events: Event[]) => Promise<void>;
|
|
6
|
+
export declare class EventQueue {
|
|
7
|
+
private queue;
|
|
8
|
+
private timer;
|
|
9
|
+
private readonly maxSize;
|
|
10
|
+
private readonly maxTime;
|
|
11
|
+
private readonly maxQueueSize;
|
|
12
|
+
private flushCallback;
|
|
13
|
+
constructor(maxSize: number, maxTime: number, maxQueueSize: number);
|
|
14
|
+
/**
|
|
15
|
+
* Sets the callback to be called when flush is triggered
|
|
16
|
+
*/
|
|
17
|
+
setFlushCallback(callback: FlushCallback): void;
|
|
18
|
+
/**
|
|
19
|
+
* Adds an event to the queue
|
|
20
|
+
*/
|
|
21
|
+
enqueue(event: Event): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Removes and returns up to `count` events from the queue
|
|
24
|
+
*/
|
|
25
|
+
dequeue(count: number): Event[];
|
|
26
|
+
/**
|
|
27
|
+
* Returns the current size of the queue
|
|
28
|
+
*/
|
|
29
|
+
size(): number;
|
|
30
|
+
/**
|
|
31
|
+
* Returns all events in the queue without removing them
|
|
32
|
+
*/
|
|
33
|
+
peek(): Event[];
|
|
34
|
+
/**
|
|
35
|
+
* Clears all events from the queue
|
|
36
|
+
*/
|
|
37
|
+
clear(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Checks if the queue size has reached the threshold
|
|
40
|
+
*/
|
|
41
|
+
private checkSizeThreshold;
|
|
42
|
+
/**
|
|
43
|
+
* Starts or restarts the flush timer
|
|
44
|
+
*/
|
|
45
|
+
private startTimer;
|
|
46
|
+
/**
|
|
47
|
+
* Stops the flush timer
|
|
48
|
+
*/
|
|
49
|
+
private stopTimer;
|
|
50
|
+
/**
|
|
51
|
+
* Flushes the queue by calling the flush callback
|
|
52
|
+
*/
|
|
53
|
+
flush(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Validates UUID format (8-4-4-4-12 hex characters)
|
|
56
|
+
*/
|
|
57
|
+
private isValidUUID;
|
|
58
|
+
/**
|
|
59
|
+
* Loads the queue from storage
|
|
60
|
+
*/
|
|
61
|
+
loadFromStorage(): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Saves the queue to storage
|
|
64
|
+
*/
|
|
65
|
+
saveToStorage(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Cleanup method to stop timers
|
|
68
|
+
*/
|
|
69
|
+
destroy(): void;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=EventQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventQueue.d.ts","sourceRoot":"","sources":["../../src/core/EventQueue.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAMtC,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/D,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,aAAa,CAA8B;gBAEvC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAMlE;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAI/C;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B1C;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE;IAM/B;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;OAEG;IACH,IAAI,IAAI,KAAK,EAAE;IAIf;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;YACW,kBAAkB;IAOhC;;OAEG;IACH,OAAO,CAAC,UAAU;IAgBlB;;OAEG;IACH,OAAO,CAAC,SAAS;IAOjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2C5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCtC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Event Queue - Manages batching logic
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EventQueue = void 0;
|
|
7
|
+
const Storage_1 = require("./Storage");
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
9
|
+
const constants_1 = require("../constants");
|
|
10
|
+
const uuid_1 = require("../utils/uuid");
|
|
11
|
+
class EventQueue {
|
|
12
|
+
constructor(maxSize, maxTime, maxQueueSize) {
|
|
13
|
+
this.queue = [];
|
|
14
|
+
this.timer = null;
|
|
15
|
+
this.flushCallback = null;
|
|
16
|
+
this.maxSize = maxSize;
|
|
17
|
+
this.maxTime = maxTime;
|
|
18
|
+
this.maxQueueSize = maxQueueSize;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sets the callback to be called when flush is triggered
|
|
22
|
+
*/
|
|
23
|
+
setFlushCallback(callback) {
|
|
24
|
+
this.flushCallback = callback;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Adds an event to the queue
|
|
28
|
+
*/
|
|
29
|
+
async enqueue(event) {
|
|
30
|
+
const queueSizeBefore = this.queue.length;
|
|
31
|
+
// Check if queue is full
|
|
32
|
+
if (this.queue.length >= this.maxQueueSize) {
|
|
33
|
+
logger_1.logger.warn(constants_1.ERROR_MESSAGES.QUEUE_FULL);
|
|
34
|
+
logger_1.logger.warn(` Queue size: ${this.queue.length}/${this.maxQueueSize}`);
|
|
35
|
+
logger_1.logger.warn(` Removing oldest event: ${this.queue[0]?.name || 'unknown'}`);
|
|
36
|
+
// Remove oldest event
|
|
37
|
+
this.queue.shift();
|
|
38
|
+
}
|
|
39
|
+
this.queue.push(event);
|
|
40
|
+
logger_1.logger.info(`Event enqueued: ${event.name}`);
|
|
41
|
+
logger_1.logger.info(` Queue size: ${queueSizeBefore} -> ${this.queue.length}/${this.maxQueueSize}`);
|
|
42
|
+
// Persist to storage
|
|
43
|
+
await this.saveToStorage();
|
|
44
|
+
// Check if we should flush
|
|
45
|
+
await this.checkSizeThreshold();
|
|
46
|
+
// Start/restart the timer
|
|
47
|
+
this.startTimer();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Removes and returns up to `count` events from the queue
|
|
51
|
+
*/
|
|
52
|
+
dequeue(count) {
|
|
53
|
+
const events = this.queue.splice(0, count);
|
|
54
|
+
// Removed verbose debug logging for production
|
|
55
|
+
return events;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the current size of the queue
|
|
59
|
+
*/
|
|
60
|
+
size() {
|
|
61
|
+
return this.queue.length;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns all events in the queue without removing them
|
|
65
|
+
*/
|
|
66
|
+
peek() {
|
|
67
|
+
return [...this.queue];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Clears all events from the queue
|
|
71
|
+
*/
|
|
72
|
+
async clear() {
|
|
73
|
+
this.queue = [];
|
|
74
|
+
this.stopTimer();
|
|
75
|
+
await this.saveToStorage();
|
|
76
|
+
// Removed verbose info logging for production
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Checks if the queue size has reached the threshold
|
|
80
|
+
*/
|
|
81
|
+
async checkSizeThreshold() {
|
|
82
|
+
if (this.queue.length >= this.maxSize) {
|
|
83
|
+
logger_1.logger.debug(`Queue size threshold reached (${this.queue.length}/${this.maxSize}), flushing...`);
|
|
84
|
+
await this.flush();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Starts or restarts the flush timer
|
|
89
|
+
*/
|
|
90
|
+
startTimer() {
|
|
91
|
+
// Stop existing timer
|
|
92
|
+
this.stopTimer();
|
|
93
|
+
// Don't start timer if queue is empty
|
|
94
|
+
if (this.queue.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Start new timer
|
|
98
|
+
this.timer = setTimeout(async () => {
|
|
99
|
+
logger_1.logger.debug(`Queue timeout reached (${this.maxTime}ms), flushing...`);
|
|
100
|
+
await this.flush();
|
|
101
|
+
}, this.maxTime);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Stops the flush timer
|
|
105
|
+
*/
|
|
106
|
+
stopTimer() {
|
|
107
|
+
if (this.timer) {
|
|
108
|
+
clearTimeout(this.timer);
|
|
109
|
+
this.timer = null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Flushes the queue by calling the flush callback
|
|
114
|
+
*/
|
|
115
|
+
async flush() {
|
|
116
|
+
if (this.queue.length === 0) {
|
|
117
|
+
logger_1.logger.debug('Queue is empty, nothing to flush');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!this.flushCallback) {
|
|
121
|
+
logger_1.logger.warn('Flush callback not set, cannot flush queue');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Stop the timer during flush
|
|
125
|
+
this.stopTimer();
|
|
126
|
+
try {
|
|
127
|
+
// Get all events
|
|
128
|
+
const events = this.dequeue(this.queue.length);
|
|
129
|
+
logger_1.logger.info(`Flushing queue: ${events.length} events`);
|
|
130
|
+
const eventNames = events.map(e => e.name).join(', ');
|
|
131
|
+
logger_1.logger.info(` Events: [${eventNames}]`);
|
|
132
|
+
// Call the flush callback
|
|
133
|
+
await this.flushCallback(events);
|
|
134
|
+
// Save updated queue to storage
|
|
135
|
+
await this.saveToStorage();
|
|
136
|
+
logger_1.logger.info(`Flushed ${events.length} events successfully`);
|
|
137
|
+
logger_1.logger.info(` Remaining queue size: ${this.queue.length}`);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logger_1.logger.error(`Failed to flush queue (${this.queue.length} events):`, error);
|
|
141
|
+
// Re-enqueue failed events
|
|
142
|
+
// Note: The BatchManager will handle this by storing failed batches
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
// Restart timer if there are still events
|
|
147
|
+
if (this.queue.length > 0) {
|
|
148
|
+
this.startTimer();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validates UUID format (8-4-4-4-12 hex characters)
|
|
154
|
+
*/
|
|
155
|
+
isValidUUID(uuid) {
|
|
156
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
157
|
+
return uuidRegex.test(uuid);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Loads the queue from storage
|
|
161
|
+
*/
|
|
162
|
+
async loadFromStorage() {
|
|
163
|
+
try {
|
|
164
|
+
const events = await Storage_1.storage.get('EVENT_QUEUE');
|
|
165
|
+
if (events && Array.isArray(events)) {
|
|
166
|
+
// Validate and fix event IDs
|
|
167
|
+
let fixedCount = 0;
|
|
168
|
+
this.queue = events.map((event) => {
|
|
169
|
+
// Fix invalid event IDs
|
|
170
|
+
if (!this.isValidUUID(event.id)) {
|
|
171
|
+
logger_1.logger.warn(`Invalid event ID detected: ${event.id}. Generating new ID.`);
|
|
172
|
+
fixedCount++;
|
|
173
|
+
return {
|
|
174
|
+
...event,
|
|
175
|
+
id: (0, uuid_1.generateUUID)(),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return event;
|
|
179
|
+
});
|
|
180
|
+
if (fixedCount > 0) {
|
|
181
|
+
logger_1.logger.info(`Fixed ${fixedCount} invalid event IDs in queue`);
|
|
182
|
+
await this.saveToStorage();
|
|
183
|
+
}
|
|
184
|
+
logger_1.logger.info(`Loaded ${this.queue.length} events from storage`);
|
|
185
|
+
// Start timer if there are events
|
|
186
|
+
if (this.queue.length > 0) {
|
|
187
|
+
this.startTimer();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
logger_1.logger.error('Failed to load queue from storage:', error);
|
|
193
|
+
this.queue = [];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Saves the queue to storage
|
|
198
|
+
*/
|
|
199
|
+
async saveToStorage() {
|
|
200
|
+
try {
|
|
201
|
+
await Storage_1.storage.set('EVENT_QUEUE', this.queue);
|
|
202
|
+
// Removed verbose debug logging for production
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
logger_1.logger.error('Failed to save queue to storage:', error);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Cleanup method to stop timers
|
|
210
|
+
*/
|
|
211
|
+
destroy() {
|
|
212
|
+
this.stopTimer();
|
|
213
|
+
// Removed verbose info logging for production
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
exports.EventQueue = EventQueue;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Layer - AsyncStorage Wrapper
|
|
3
|
+
*/
|
|
4
|
+
import type { StorageKey, StorageValue } from '../types/storage';
|
|
5
|
+
declare class Storage {
|
|
6
|
+
/**
|
|
7
|
+
* Sets a value in storage
|
|
8
|
+
*/
|
|
9
|
+
set<K extends StorageKey>(key: K, value: StorageValue<K>): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Gets a value from storage
|
|
12
|
+
*/
|
|
13
|
+
get<K extends StorageKey>(key: K): Promise<StorageValue<K> | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Removes a value from storage
|
|
16
|
+
*/
|
|
17
|
+
remove(key: StorageKey): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Clears all SDK-related storage
|
|
20
|
+
*/
|
|
21
|
+
clear(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a key exists in storage
|
|
24
|
+
*/
|
|
25
|
+
has(key: StorageKey): Promise<boolean>;
|
|
26
|
+
}
|
|
27
|
+
export declare const storage: Storage;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=Storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../src/core/Storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGjE,cAAM,OAAO;IACX;;OAEG;IACG,GAAG,CAAC,CAAC,SAAS,UAAU,EAC5B,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC;IAYhB;;OAEG;IACG,GAAG,CAAC,CAAC,SAAS,UAAU,EAC5B,GAAG,EAAE,CAAC,GACL,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAiBlC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ7C;AAED,eAAO,MAAM,OAAO,SAAgB,CAAC"}
|