@mostly-good-metrics/javascript 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.
- package/README.md +319 -0
- package/dist/cjs/client.js +416 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/index.js +65 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/logger.js +64 -0
- package/dist/cjs/logger.js.map +1 -0
- package/dist/cjs/network.js +192 -0
- package/dist/cjs/network.js.map +1 -0
- package/dist/cjs/storage.js +227 -0
- package/dist/cjs/storage.js.map +1 -0
- package/dist/cjs/types.js +70 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.js +249 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/client.js +412 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logger.js +55 -0
- package/dist/esm/logger.js.map +1 -0
- package/dist/esm/network.js +187 -0
- package/dist/esm/network.js.map +1 -0
- package/dist/esm/storage.js +221 -0
- package/dist/esm/storage.js.map +1 -0
- package/dist/esm/types.js +66 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.js +236 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/client.d.ts +126 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logger.d.ts +37 -0
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/network.d.ts +28 -0
- package/dist/types/network.d.ts.map +1 -0
- package/dist/types/storage.d.ts +76 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/types.d.ts +279 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +48 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +68 -0
- package/src/client.test.ts +346 -0
- package/src/client.ts +510 -0
- package/src/index.ts +79 -0
- package/src/logger.ts +63 -0
- package/src/network.ts +230 -0
- package/src/storage.test.ts +175 -0
- package/src/storage.ts +249 -0
- package/src/types.ts +347 -0
- package/src/utils.test.ts +239 -0
- package/src/utils.ts +315 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FetchNetworkClient = void 0;
|
|
4
|
+
exports.createDefaultNetworkClient = createDefaultNetworkClient;
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
const types_1 = require("./types");
|
|
7
|
+
const EVENTS_ENDPOINT = '/v1/events';
|
|
8
|
+
const REQUEST_TIMEOUT_MS = 60000; // 60 seconds
|
|
9
|
+
/**
|
|
10
|
+
* Compress data using gzip if available (browser CompressionStream API).
|
|
11
|
+
* Falls back to uncompressed data if compression is not available.
|
|
12
|
+
*/
|
|
13
|
+
async function compressIfNeeded(data) {
|
|
14
|
+
const bytes = new TextEncoder().encode(data);
|
|
15
|
+
// Only compress if payload exceeds threshold
|
|
16
|
+
if (bytes.length < types_1.Constraints.COMPRESSION_THRESHOLD_BYTES) {
|
|
17
|
+
return { data, compressed: false };
|
|
18
|
+
}
|
|
19
|
+
// Check if CompressionStream is available (modern browsers)
|
|
20
|
+
if (typeof CompressionStream === 'undefined') {
|
|
21
|
+
logger_1.logger.debug('CompressionStream not available, sending uncompressed');
|
|
22
|
+
return { data, compressed: false };
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const stream = new Blob([bytes]).stream();
|
|
26
|
+
const compressedStream = stream.pipeThrough(new CompressionStream('gzip'));
|
|
27
|
+
const compressedBlob = await new Response(compressedStream).blob();
|
|
28
|
+
logger_1.logger.debug(`Compressed payload from ${bytes.length} to ${compressedBlob.size} bytes`);
|
|
29
|
+
return { data: compressedBlob, compressed: true };
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
logger_1.logger.warn('Failed to compress payload, sending uncompressed', e);
|
|
33
|
+
return { data, compressed: false };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Default network client using the Fetch API.
|
|
38
|
+
*/
|
|
39
|
+
class FetchNetworkClient {
|
|
40
|
+
constructor() {
|
|
41
|
+
this.retryAfterTime = null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Send events to the MostlyGoodMetrics API.
|
|
45
|
+
*/
|
|
46
|
+
async sendEvents(payload, config) {
|
|
47
|
+
// Check rate limiting
|
|
48
|
+
if (this.isRateLimited()) {
|
|
49
|
+
const retryAfter = this.getRetryAfterTime();
|
|
50
|
+
const waitMs = retryAfter ? retryAfter.getTime() - Date.now() : 0;
|
|
51
|
+
logger_1.logger.debug(`Rate limited, retry after ${Math.ceil(waitMs / 1000)}s`);
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
error: new types_1.MGMError('RATE_LIMITED', 'Rate limited, please retry later', {
|
|
55
|
+
retryAfter: Math.ceil(waitMs / 1000),
|
|
56
|
+
}),
|
|
57
|
+
shouldRetry: true,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const url = `${config.baseURL}${EVENTS_ENDPOINT}`;
|
|
61
|
+
const jsonBody = JSON.stringify(payload);
|
|
62
|
+
const { data, compressed } = await compressIfNeeded(jsonBody);
|
|
63
|
+
const headers = {
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
'X-MGM-Key': config.apiKey,
|
|
66
|
+
};
|
|
67
|
+
if (config.bundleId) {
|
|
68
|
+
headers['X-MGM-Bundle-Id'] = config.bundleId;
|
|
69
|
+
}
|
|
70
|
+
if (compressed) {
|
|
71
|
+
headers['Content-Encoding'] = 'gzip';
|
|
72
|
+
}
|
|
73
|
+
logger_1.logger.debug(`Sending ${payload.events.length} events to ${url}`);
|
|
74
|
+
try {
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
77
|
+
const response = await fetch(url, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers,
|
|
80
|
+
body: data,
|
|
81
|
+
signal: controller.signal,
|
|
82
|
+
});
|
|
83
|
+
clearTimeout(timeoutId);
|
|
84
|
+
return this.handleResponse(response);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
if (e instanceof Error && e.name === 'AbortError') {
|
|
88
|
+
logger_1.logger.warn('Request timed out');
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: new types_1.MGMError('NETWORK_ERROR', 'Request timed out'),
|
|
92
|
+
shouldRetry: true,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
logger_1.logger.error('Network error', e);
|
|
96
|
+
return {
|
|
97
|
+
success: false,
|
|
98
|
+
error: new types_1.MGMError('NETWORK_ERROR', e instanceof Error ? e.message : 'Unknown network error'),
|
|
99
|
+
shouldRetry: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Handle the API response and return appropriate result.
|
|
105
|
+
*/
|
|
106
|
+
handleResponse(response) {
|
|
107
|
+
const statusCode = response.status;
|
|
108
|
+
// Success
|
|
109
|
+
if (statusCode === 204 || statusCode === 200) {
|
|
110
|
+
logger_1.logger.debug('Events sent successfully');
|
|
111
|
+
return { success: true };
|
|
112
|
+
}
|
|
113
|
+
// Rate limited
|
|
114
|
+
if (statusCode === 429) {
|
|
115
|
+
const retryAfterHeader = response.headers.get('Retry-After');
|
|
116
|
+
const retryAfterSeconds = retryAfterHeader ? parseInt(retryAfterHeader, 10) : 60;
|
|
117
|
+
this.retryAfterTime = new Date(Date.now() + retryAfterSeconds * 1000);
|
|
118
|
+
logger_1.logger.warn(`Rate limited, retry after ${retryAfterSeconds}s`);
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
error: new types_1.MGMError('RATE_LIMITED', 'Rate limited by server', {
|
|
122
|
+
retryAfter: retryAfterSeconds,
|
|
123
|
+
statusCode,
|
|
124
|
+
}),
|
|
125
|
+
shouldRetry: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Client errors (4xx) - don't retry, drop events
|
|
129
|
+
if (statusCode >= 400 && statusCode < 500) {
|
|
130
|
+
const errorType = statusCode === 400
|
|
131
|
+
? 'BAD_REQUEST'
|
|
132
|
+
: statusCode === 401
|
|
133
|
+
? 'UNAUTHORIZED'
|
|
134
|
+
: statusCode === 403
|
|
135
|
+
? 'FORBIDDEN'
|
|
136
|
+
: 'BAD_REQUEST';
|
|
137
|
+
const errorMessage = `Server returned ${statusCode}`;
|
|
138
|
+
logger_1.logger.error(errorMessage);
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
error: new types_1.MGMError(errorType, errorMessage, { statusCode }),
|
|
142
|
+
shouldRetry: false, // Drop events on client errors
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// Server errors (5xx) - retry later
|
|
146
|
+
if (statusCode >= 500) {
|
|
147
|
+
const errorMessage = `Server error: ${statusCode}`;
|
|
148
|
+
logger_1.logger.warn(errorMessage);
|
|
149
|
+
return {
|
|
150
|
+
success: false,
|
|
151
|
+
error: new types_1.MGMError('SERVER_ERROR', errorMessage, { statusCode }),
|
|
152
|
+
shouldRetry: true,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Unexpected status code
|
|
156
|
+
logger_1.logger.warn(`Unexpected status code: ${statusCode}`);
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
error: new types_1.MGMError('UNKNOWN_ERROR', `Unexpected status code: ${statusCode}`, {
|
|
160
|
+
statusCode,
|
|
161
|
+
}),
|
|
162
|
+
shouldRetry: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check if currently rate limited.
|
|
167
|
+
*/
|
|
168
|
+
isRateLimited() {
|
|
169
|
+
if (!this.retryAfterTime) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (Date.now() >= this.retryAfterTime.getTime()) {
|
|
173
|
+
this.retryAfterTime = null;
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the time when rate limiting expires.
|
|
180
|
+
*/
|
|
181
|
+
getRetryAfterTime() {
|
|
182
|
+
return this.retryAfterTime;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.FetchNetworkClient = FetchNetworkClient;
|
|
186
|
+
/**
|
|
187
|
+
* Create the default network client.
|
|
188
|
+
*/
|
|
189
|
+
function createDefaultNetworkClient() {
|
|
190
|
+
return new FetchNetworkClient();
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.persistence = exports.LocalStorageEventStorage = exports.InMemoryEventStorage = void 0;
|
|
4
|
+
exports.createDefaultStorage = createDefaultStorage;
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
const types_1 = require("./types");
|
|
7
|
+
const STORAGE_KEY = 'mostlygoodmetrics_events';
|
|
8
|
+
const USER_ID_KEY = 'mostlygoodmetrics_user_id';
|
|
9
|
+
const APP_VERSION_KEY = 'mostlygoodmetrics_app_version';
|
|
10
|
+
/**
|
|
11
|
+
* Check if we're running in a browser environment with localStorage available.
|
|
12
|
+
*/
|
|
13
|
+
function isLocalStorageAvailable() {
|
|
14
|
+
try {
|
|
15
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const testKey = '__mgm_test__';
|
|
19
|
+
localStorage.setItem(testKey, 'test');
|
|
20
|
+
localStorage.removeItem(testKey);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* In-memory event storage implementation.
|
|
29
|
+
* Used as a fallback when localStorage is not available,
|
|
30
|
+
* or for testing purposes.
|
|
31
|
+
*/
|
|
32
|
+
class InMemoryEventStorage {
|
|
33
|
+
constructor(maxEvents = types_1.Constraints.MIN_STORED_EVENTS) {
|
|
34
|
+
this.events = [];
|
|
35
|
+
this.maxEvents = Math.max(maxEvents, types_1.Constraints.MIN_STORED_EVENTS);
|
|
36
|
+
}
|
|
37
|
+
async store(event) {
|
|
38
|
+
this.events.push(event);
|
|
39
|
+
// Trim oldest events if we exceed the limit
|
|
40
|
+
if (this.events.length > this.maxEvents) {
|
|
41
|
+
const excess = this.events.length - this.maxEvents;
|
|
42
|
+
this.events.splice(0, excess);
|
|
43
|
+
logger_1.logger.debug(`Dropped ${excess} oldest events due to storage limit`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async fetchEvents(limit) {
|
|
47
|
+
return this.events.slice(0, limit);
|
|
48
|
+
}
|
|
49
|
+
async removeEvents(count) {
|
|
50
|
+
this.events.splice(0, count);
|
|
51
|
+
}
|
|
52
|
+
async eventCount() {
|
|
53
|
+
return this.events.length;
|
|
54
|
+
}
|
|
55
|
+
async clear() {
|
|
56
|
+
this.events = [];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update the maximum number of stored events.
|
|
60
|
+
*/
|
|
61
|
+
setMaxEvents(maxEvents) {
|
|
62
|
+
this.maxEvents = Math.max(maxEvents, types_1.Constraints.MIN_STORED_EVENTS);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.InMemoryEventStorage = InMemoryEventStorage;
|
|
66
|
+
/**
|
|
67
|
+
* LocalStorage-based event storage implementation.
|
|
68
|
+
* Persists events across page reloads and browser restarts.
|
|
69
|
+
*/
|
|
70
|
+
class LocalStorageEventStorage {
|
|
71
|
+
constructor(maxEvents = types_1.Constraints.MIN_STORED_EVENTS) {
|
|
72
|
+
this.events = null;
|
|
73
|
+
this.maxEvents = Math.max(maxEvents, types_1.Constraints.MIN_STORED_EVENTS);
|
|
74
|
+
}
|
|
75
|
+
loadEvents() {
|
|
76
|
+
if (this.events !== null) {
|
|
77
|
+
return this.events;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
81
|
+
if (stored) {
|
|
82
|
+
this.events = JSON.parse(stored);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.events = [];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
logger_1.logger.warn('Failed to load events from localStorage', e);
|
|
90
|
+
this.events = [];
|
|
91
|
+
}
|
|
92
|
+
return this.events;
|
|
93
|
+
}
|
|
94
|
+
saveEvents() {
|
|
95
|
+
try {
|
|
96
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.events ?? []));
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
logger_1.logger.error('Failed to save events to localStorage', e);
|
|
100
|
+
throw new types_1.MGMError('STORAGE_ERROR', 'Failed to save events to localStorage');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async store(event) {
|
|
104
|
+
const events = this.loadEvents();
|
|
105
|
+
events.push(event);
|
|
106
|
+
// Trim oldest events if we exceed the limit
|
|
107
|
+
if (events.length > this.maxEvents) {
|
|
108
|
+
const excess = events.length - this.maxEvents;
|
|
109
|
+
events.splice(0, excess);
|
|
110
|
+
logger_1.logger.debug(`Dropped ${excess} oldest events due to storage limit`);
|
|
111
|
+
}
|
|
112
|
+
this.saveEvents();
|
|
113
|
+
}
|
|
114
|
+
async fetchEvents(limit) {
|
|
115
|
+
const events = this.loadEvents();
|
|
116
|
+
return events.slice(0, limit);
|
|
117
|
+
}
|
|
118
|
+
async removeEvents(count) {
|
|
119
|
+
const events = this.loadEvents();
|
|
120
|
+
events.splice(0, count);
|
|
121
|
+
this.saveEvents();
|
|
122
|
+
}
|
|
123
|
+
async eventCount() {
|
|
124
|
+
return this.loadEvents().length;
|
|
125
|
+
}
|
|
126
|
+
async clear() {
|
|
127
|
+
this.events = [];
|
|
128
|
+
try {
|
|
129
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
logger_1.logger.warn('Failed to clear events from localStorage', e);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Update the maximum number of stored events.
|
|
137
|
+
*/
|
|
138
|
+
setMaxEvents(maxEvents) {
|
|
139
|
+
this.maxEvents = Math.max(maxEvents, types_1.Constraints.MIN_STORED_EVENTS);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.LocalStorageEventStorage = LocalStorageEventStorage;
|
|
143
|
+
/**
|
|
144
|
+
* Create the appropriate storage implementation based on the environment.
|
|
145
|
+
*/
|
|
146
|
+
function createDefaultStorage(maxEvents) {
|
|
147
|
+
if (isLocalStorageAvailable()) {
|
|
148
|
+
logger_1.logger.debug('Using LocalStorage for event persistence');
|
|
149
|
+
return new LocalStorageEventStorage(maxEvents);
|
|
150
|
+
}
|
|
151
|
+
logger_1.logger.debug('LocalStorage not available, using in-memory storage');
|
|
152
|
+
return new InMemoryEventStorage(maxEvents);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Persistence helpers for user ID and app version.
|
|
156
|
+
* These use localStorage when available, otherwise fall back to in-memory.
|
|
157
|
+
*/
|
|
158
|
+
class PersistenceManager {
|
|
159
|
+
constructor() {
|
|
160
|
+
this.inMemoryUserId = null;
|
|
161
|
+
this.inMemoryAppVersion = null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the persisted user ID.
|
|
165
|
+
*/
|
|
166
|
+
getUserId() {
|
|
167
|
+
if (isLocalStorageAvailable()) {
|
|
168
|
+
return localStorage.getItem(USER_ID_KEY);
|
|
169
|
+
}
|
|
170
|
+
return this.inMemoryUserId;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Set the user ID (persists across sessions).
|
|
174
|
+
*/
|
|
175
|
+
setUserId(userId) {
|
|
176
|
+
if (isLocalStorageAvailable()) {
|
|
177
|
+
if (userId) {
|
|
178
|
+
localStorage.setItem(USER_ID_KEY, userId);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
localStorage.removeItem(USER_ID_KEY);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.inMemoryUserId = userId;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get the persisted app version (for detecting updates).
|
|
188
|
+
*/
|
|
189
|
+
getAppVersion() {
|
|
190
|
+
if (isLocalStorageAvailable()) {
|
|
191
|
+
return localStorage.getItem(APP_VERSION_KEY);
|
|
192
|
+
}
|
|
193
|
+
return this.inMemoryAppVersion;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Set the app version.
|
|
197
|
+
*/
|
|
198
|
+
setAppVersion(version) {
|
|
199
|
+
if (isLocalStorageAvailable()) {
|
|
200
|
+
if (version) {
|
|
201
|
+
localStorage.setItem(APP_VERSION_KEY, version);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
localStorage.removeItem(APP_VERSION_KEY);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.inMemoryAppVersion = version;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check if this is the first time the app has been opened.
|
|
211
|
+
* Uses localStorage to detect first-ever installation.
|
|
212
|
+
*/
|
|
213
|
+
isFirstLaunch() {
|
|
214
|
+
const FIRST_LAUNCH_KEY = 'mostlygoodmetrics_installed';
|
|
215
|
+
if (!isLocalStorageAvailable()) {
|
|
216
|
+
return false; // Can't reliably detect without persistence
|
|
217
|
+
}
|
|
218
|
+
const hasLaunched = localStorage.getItem(FIRST_LAUNCH_KEY);
|
|
219
|
+
if (!hasLaunched) {
|
|
220
|
+
localStorage.setItem(FIRST_LAUNCH_KEY, 'true');
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
exports.persistence = new PersistenceManager();
|
|
227
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EVENT_NAME_REGEX = exports.Constraints = exports.DefaultConfiguration = exports.SystemProperties = exports.SystemEvents = exports.MGMError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Custom error class for SDK errors.
|
|
6
|
+
*/
|
|
7
|
+
class MGMError extends Error {
|
|
8
|
+
constructor(type, message, options) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'MGMError';
|
|
11
|
+
this.type = type;
|
|
12
|
+
this.retryAfter = options?.retryAfter;
|
|
13
|
+
this.statusCode = options?.statusCode;
|
|
14
|
+
// Maintains proper stack trace for where error was thrown (V8 engines)
|
|
15
|
+
if (Error.captureStackTrace) {
|
|
16
|
+
Error.captureStackTrace(this, MGMError);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.MGMError = MGMError;
|
|
21
|
+
/**
|
|
22
|
+
* System event names (prefixed with $).
|
|
23
|
+
*/
|
|
24
|
+
exports.SystemEvents = {
|
|
25
|
+
APP_INSTALLED: '$app_installed',
|
|
26
|
+
APP_UPDATED: '$app_updated',
|
|
27
|
+
APP_OPENED: '$app_opened',
|
|
28
|
+
APP_BACKGROUNDED: '$app_backgrounded',
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* System property keys (prefixed with $).
|
|
32
|
+
*/
|
|
33
|
+
exports.SystemProperties = {
|
|
34
|
+
DEVICE_TYPE: '$device_type',
|
|
35
|
+
DEVICE_MODEL: '$device_model',
|
|
36
|
+
VERSION: '$version',
|
|
37
|
+
PREVIOUS_VERSION: '$previous_version',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Default configuration values.
|
|
41
|
+
*/
|
|
42
|
+
exports.DefaultConfiguration = {
|
|
43
|
+
baseURL: 'https://mostlygoodmetrics.com',
|
|
44
|
+
environment: 'production',
|
|
45
|
+
maxBatchSize: 100,
|
|
46
|
+
flushInterval: 30,
|
|
47
|
+
maxStoredEvents: 10000,
|
|
48
|
+
enableDebugLogging: false,
|
|
49
|
+
trackAppLifecycleEvents: true,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Validation constraints.
|
|
53
|
+
*/
|
|
54
|
+
exports.Constraints = {
|
|
55
|
+
MAX_EVENT_NAME_LENGTH: 255,
|
|
56
|
+
MAX_BATCH_SIZE: 1000,
|
|
57
|
+
MIN_BATCH_SIZE: 1,
|
|
58
|
+
MIN_FLUSH_INTERVAL: 1,
|
|
59
|
+
MIN_STORED_EVENTS: 100,
|
|
60
|
+
MAX_STRING_PROPERTY_LENGTH: 1000,
|
|
61
|
+
MAX_PROPERTY_DEPTH: 3,
|
|
62
|
+
MAX_PROPERTY_SIZE_BYTES: 10 * 1024, // 10KB
|
|
63
|
+
COMPRESSION_THRESHOLD_BYTES: 1024, // 1KB
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Regular expression for validating event names.
|
|
67
|
+
* Must start with a letter (or $ for system events) followed by alphanumeric and underscores.
|
|
68
|
+
*/
|
|
69
|
+
exports.EVENT_NAME_REGEX = /^\$?[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
70
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";;;AA4QA;;GAEG;AACH,MAAa,QAAS,SAAQ,KAAK;IAKjC,YACE,IAAkB,EAClB,OAAe,EACf,OAAsD;QAEtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,CAAC;QAEtC,uEAAuE;QACvE,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;CACF;AArBD,4BAqBC;AAED;;GAEG;AACU,QAAA,YAAY,GAAG;IAC1B,aAAa,EAAE,gBAAgB;IAC/B,WAAW,EAAE,cAAc;IAC3B,UAAU,EAAE,aAAa;IACzB,gBAAgB,EAAE,mBAAmB;CAC7B,CAAC;AAEX;;GAEG;AACU,QAAA,gBAAgB,GAAG;IAC9B,WAAW,EAAE,cAAc;IAC3B,YAAY,EAAE,eAAe;IAC7B,OAAO,EAAE,UAAU;IACnB,gBAAgB,EAAE,mBAAmB;CAC7B,CAAC;AAEX;;GAEG;AACU,QAAA,oBAAoB,GAAG;IAClC,OAAO,EAAE,+BAA+B;IACxC,WAAW,EAAE,YAAY;IACzB,YAAY,EAAE,GAAG;IACjB,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,KAAK;IACtB,kBAAkB,EAAE,KAAK;IACzB,uBAAuB,EAAE,IAAI;CACrB,CAAC;AAEX;;GAEG;AACU,QAAA,WAAW,GAAG;IACzB,qBAAqB,EAAE,GAAG;IAC1B,cAAc,EAAE,IAAI;IACpB,cAAc,EAAE,CAAC;IACjB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,GAAG;IACtB,0BAA0B,EAAE,IAAI;IAChC,kBAAkB,EAAE,CAAC;IACrB,uBAAuB,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO;IAC3C,2BAA2B,EAAE,IAAI,EAAE,MAAM;CACjC,CAAC;AAEX;;;GAGG;AACU,QAAA,gBAAgB,GAAG,4BAA4B,CAAC"}
|