@oxyhq/services
Version:
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
177 lines (163 loc) • 6.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DeviceManager = void 0;
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/**
* Client-side device management utility
* Handles persistent device identification across app sessions
*/
class DeviceManager {
static DEVICE_KEY = 'oxy_device_info';
/**
* Check if we're in React Native environment
*/
static isReactNative() {
return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
}
/**
* Get appropriate storage for the platform
*/
static async getStorage() {
if (this.isReactNative()) {
try {
const asyncStorageModule = await Promise.resolve().then(() => _interopRequireWildcard(require('@react-native-async-storage/async-storage')));
const storage = asyncStorageModule.default;
return {
getItem: storage.getItem.bind(storage),
setItem: storage.setItem.bind(storage),
removeItem: storage.removeItem.bind(storage)
};
} catch (error) {
console.error('AsyncStorage not available in React Native:', error);
throw new Error('AsyncStorage is required in React Native environment');
}
} else {
// Use localStorage for web
return {
getItem: async key => localStorage.getItem(key),
setItem: async (key, value) => localStorage.setItem(key, value),
removeItem: async key => localStorage.removeItem(key)
};
}
}
/**
* Get or create device fingerprint for current device
*/
static getDeviceFingerprint() {
const fingerprint = {
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown',
platform: typeof navigator !== 'undefined' ? navigator.platform : 'unknown',
language: typeof navigator !== 'undefined' ? navigator.language : undefined,
timezone: typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : undefined
};
// Add screen info if available
if (typeof screen !== 'undefined') {
fingerprint.screen = {
width: screen.width,
height: screen.height,
colorDepth: screen.colorDepth
};
}
return fingerprint;
}
/**
* Get stored device info or create new one
*/
static async getDeviceInfo() {
try {
const storage = await this.getStorage();
const stored = await storage.getItem(this.DEVICE_KEY);
if (stored) {
const deviceInfo = JSON.parse(stored);
// Update last used timestamp
deviceInfo.lastUsed = new Date().toISOString();
await this.saveDeviceInfo(deviceInfo);
return deviceInfo;
}
// Create new device info
return await this.createNewDeviceInfo();
} catch (error) {
console.error('Error getting device info:', error);
return await this.createNewDeviceInfo();
}
}
/**
* Create new device info and store it
*/
static async createNewDeviceInfo() {
const deviceInfo = {
deviceId: this.generateDeviceId(),
fingerprint: JSON.stringify(this.getDeviceFingerprint()),
createdAt: new Date().toISOString(),
lastUsed: new Date().toISOString()
};
await this.saveDeviceInfo(deviceInfo);
return deviceInfo;
}
/**
* Save device info to storage
*/
static async saveDeviceInfo(deviceInfo) {
try {
const storage = await this.getStorage();
await storage.setItem(this.DEVICE_KEY, JSON.stringify(deviceInfo));
} catch (error) {
console.error('Error saving device info:', error);
}
}
/**
* Update device name
*/
static async updateDeviceName(deviceName) {
try {
const deviceInfo = await this.getDeviceInfo();
deviceInfo.deviceName = deviceName;
await this.saveDeviceInfo(deviceInfo);
} catch (error) {
console.error('Error updating device name:', error);
}
}
/**
* Clear stored device info (useful for testing or reset)
*/
static async clearDeviceInfo() {
try {
const storage = await this.getStorage();
await storage.removeItem(this.DEVICE_KEY);
} catch (error) {
console.error('Error clearing device info:', error);
}
}
/**
* Generate a unique device ID
*/
static generateDeviceId() {
// Use crypto.getRandomValues if available, otherwise fallback to Math.random
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
} else {
// Fallback for environments without crypto.getRandomValues
return 'device_' + Date.now().toString(36) + Math.random().toString(36).substr(2);
}
}
/**
* Get a user-friendly device name based on platform
*/
static getDefaultDeviceName() {
const fingerprint = this.getDeviceFingerprint();
const platform = (fingerprint.platform || '').toLowerCase();
if (platform.includes('win')) return 'Windows Computer';
if (platform.includes('mac')) return 'Mac Computer';
if (platform.includes('linux')) return 'Linux Computer';
if (platform.includes('iphone')) return 'iPhone';
if (platform.includes('ipad')) return 'iPad';
if (platform.includes('android')) return 'Android Device';
return 'Unknown Device';
}
}
exports.DeviceManager = DeviceManager;
//# sourceMappingURL=deviceManager.js.map