@mostly-good-metrics/javascript 0.1.0 → 0.4.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/src/utils.test.ts CHANGED
@@ -5,6 +5,8 @@ import {
5
5
  validateEventName,
6
6
  sanitizeProperties,
7
7
  resolveConfiguration,
8
+ getLocale,
9
+ getTimezone,
8
10
  } from './utils';
9
11
  import { Constraints, DefaultConfiguration, MGMError } from './types';
10
12
 
@@ -237,3 +239,32 @@ describe('resolveConfiguration', () => {
237
239
  expect(config.maxStoredEvents).toBe(Constraints.MIN_STORED_EVENTS);
238
240
  });
239
241
  });
242
+
243
+ describe('getLocale', () => {
244
+ it('should return a non-empty string', () => {
245
+ const locale = getLocale();
246
+ expect(typeof locale).toBe('string');
247
+ expect(locale.length).toBeGreaterThan(0);
248
+ });
249
+
250
+ it('should return a locale-like string (e.g., en, en-US)', () => {
251
+ const locale = getLocale();
252
+ // Locale should be something like "en", "en-US", "fr-FR", etc.
253
+ expect(locale).toMatch(/^[a-z]{2}(-[A-Z]{2})?$/i);
254
+ });
255
+ });
256
+
257
+ describe('getTimezone', () => {
258
+ it('should return a string', () => {
259
+ const timezone = getTimezone();
260
+ expect(typeof timezone).toBe('string');
261
+ });
262
+
263
+ it('should return a valid IANA timezone or empty string', () => {
264
+ const timezone = getTimezone();
265
+ // Should be empty or a valid IANA timezone like "America/New_York" or "UTC"
266
+ if (timezone) {
267
+ expect(timezone).toMatch(/^([A-Za-z_]+\/[A-Za-z_]+|UTC)$/);
268
+ }
269
+ });
270
+ });
package/src/utils.ts CHANGED
@@ -178,6 +178,8 @@ export function resolveConfiguration(config: MGMConfiguration): ResolvedConfigur
178
178
  bundleId: config.bundleId ?? detectBundleId(),
179
179
  appVersion: config.appVersion ?? '',
180
180
  osVersion: config.osVersion ?? '',
181
+ platform: config.platform ?? detectPlatform(),
182
+ sdk: config.sdk ?? 'javascript',
181
183
  storage: config.storage,
182
184
  networkClient: config.networkClient,
183
185
  };
@@ -198,14 +200,9 @@ function detectBundleId(): string {
198
200
 
199
201
  /**
200
202
  * Detect the current platform.
203
+ * Note: For React Native, the platform should be passed via config (ios/android).
201
204
  */
202
205
  export function detectPlatform(): Platform {
203
- // Check for React Native / Expo
204
- if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
205
- // Could check for Expo-specific globals here
206
- return 'react-native';
207
- }
208
-
209
206
  // Check for Node.js
210
207
  if (typeof process !== 'undefined' && process.versions?.node) {
211
208
  return 'node';
@@ -313,3 +310,24 @@ export function getDeviceModel(): string {
313
310
  export function delay(ms: number): Promise<void> {
314
311
  return new Promise((resolve) => setTimeout(resolve, ms));
315
312
  }
313
+
314
+ /**
315
+ * Get the user's locale.
316
+ */
317
+ export function getLocale(): string {
318
+ if (typeof navigator !== 'undefined') {
319
+ return navigator.language || 'en';
320
+ }
321
+ return 'en';
322
+ }
323
+
324
+ /**
325
+ * Get the user's timezone.
326
+ */
327
+ export function getTimezone(): string {
328
+ try {
329
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || '';
330
+ } catch {
331
+ return '';
332
+ }
333
+ }