Device

Detect device characteristics, monitor network and battery status, track visibility changes, and generate browser fingerprints. Access via Aura.device.

Quick Start

js
import Aura from 'aura.js';

Aura.init();

// Read device info
const { deviceType, os, screen, touch } = Aura.device.info;
console.log(`${deviceType} on ${os}, ${screen.width}x${screen.height}`);

// Monitor connectivity
const unsub = Aura.device.onOnlineChange(online => {
  console.log(online ? 'Back online' : 'Went offline');
});

// Generate a fingerprint
const fp = await Aura.device.fingerprint();
console.log('Fingerprint:', fp);

info

A read-only property that lazily collects and caches device information on first access. Returns a DeviceInfo object with browser, screen, touch, device type, and OS details. A persistent id is stored in local storage and reused across sessions.

get info: DeviceInfo
js
const info = Aura.device.info;

console.log(info.id);                // persistent UUID
console.log(info.browser.language); // "en-US"
console.log(info.screen.pixelRatio); // 2
console.log(info.deviceType);         // "desktop" | "mobile" | "tablet"
console.log(info.os);                 // "mac" | "ios" | "android" | "windows" | "linux" | "unknown"
console.log(info.touch);              // true / false

getNetwork()

Returns current network information including online status, connection type, downlink speed, round-trip time, and effective connection type. Uses the Network Information API where available.

getNetwork(): NetworkInfo
js
const net = Aura.device.getNetwork();

console.log(net.online);        // true
console.log(net.type);          // "wifi"
console.log(net.downlink);      // 10 (Mbps)
console.log(net.rtt);           // 50 (ms)
console.log(net.effectiveType); // "4g"

checkPermission()

Queries the browser Permissions API for the given permission name. Returns 'prompt' as a fallback if the API is unavailable.

async checkPermission(name: PermissionName): Promise<PermissionState>
ParamTypeDescription
namePermissionNameThe permission to query, e.g. 'geolocation', 'notifications', 'camera'
js
const state = await Aura.device.checkPermission('notifications');
// "granted" | "denied" | "prompt"

if (state === 'granted') {
  // safe to use Notifications API
}

getStorageQuota()

Returns estimated storage usage and quota in bytes via the Storage Manager API. Returns null if the API is not available.

async getStorageQuota(): Promise<{ usage: number; quota: number } | null>
js
const quota = await Aura.device.getStorageQuota();

if (quota) {
  const usedMB = (quota.usage / 1024 / 1024).toFixed(2);
  const totalMB = (quota.quota / 1024 / 1024).toFixed(2);
  console.log(`Storage: ${usedMB} MB / ${totalMB} MB`);
}

prefersDarkMode()

Returns true if the user's OS or browser is set to dark mode, using the prefers-color-scheme media query.

prefersDarkMode(): boolean
js
if (Aura.device.prefersDarkMode()) {
  document.body.classList.add('dark-theme');
}

onDarkModeChange()

Listens for changes to the user's color scheme preference. Returns an unsubscribe function to stop listening.

onDarkModeChange(fn: (dark: boolean) => void): () => void
ParamTypeDescription
fn(dark: boolean) => voidCallback invoked with true when dark mode activates, false when it deactivates
js
const unsub = Aura.device.onDarkModeChange(dark => {
  document.body.classList.toggle('dark-theme', dark);
});

// Later: stop listening
unsub();

getBattery()

Returns battery level (0-1) and charging status. Returns null if the Battery Status API is unavailable.

async getBattery(): Promise<{ level: number; charging: boolean } | null>
js
const battery = await Aura.device.getBattery();

if (battery) {
  console.log(`Battery: ${(battery.level * 100).toFixed(0)}%`);
  console.log(`Charging: ${battery.charging}`);
}

onVisibilityChange()

Fires a callback whenever the page visibility changes (e.g. user switches tabs). Returns an unsubscribe function.

onVisibilityChange(fn: (visible: boolean) => void): () => void
ParamTypeDescription
fn(visible: boolean) => voidCallback invoked with true when page becomes visible, false when hidden
js
const unsub = Aura.device.onVisibilityChange(visible => {
  if (visible) {
    console.log('Tab is active — resume polling');
  } else {
    console.log('Tab is hidden — pause polling');
  }
});

unsub();

isOnline()

Returns the current online status of the browser. A simple wrapper around navigator.onLine.

isOnline(): boolean
js
if (!Aura.device.isOnline()) {
  showOfflineBanner();
}

onOnlineChange()

Listens for online/offline transitions. Registers both online and offline window events. Returns an unsubscribe function that removes both listeners.

onOnlineChange(fn: (online: boolean) => void): () => void
ParamTypeDescription
fn(online: boolean) => voidCallback invoked with true when going online, false when going offline
js
const unsub = Aura.device.onOnlineChange(online => {
  Aura.state.set('network.online', online);
});

// Clean up
unsub();

fingerprint()

Generates a SHA-256 browser fingerprint from device info (user agent, platform, language, screen dimensions, touch support, OS, and timezone). The result is cached after the first call.

async fingerprint(): Promise<string>
js
const fp = await Aura.device.fingerprint();
console.log(fp); // "a3f8c2e1b9d047..."

hash()

Hashes an arbitrary string using SHA-256 (via crypto.subtle). Falls back to a simple 32-bit hash when the SubtleCrypto API is unavailable.

async hash(input: string): Promise<string>
ParamTypeDescription
inputstringThe string to hash
js
const hashed = await Aura.device.hash('my-secret-data');
console.log(hashed); // hex-encoded SHA-256 string

Types

DeviceInfo

ts
interface DeviceInfo {
  id: string;
  browser: {
    userAgent: string;
    platform: string;
    language: string;
    languages: readonly string[];
  };
  screen: {
    width: number;
    height: number;
    pixelRatio: number;
  };
  touch: boolean;
  deviceType: 'mobile' | 'tablet' | 'desktop';
  os: 'ios' | 'android' | 'windows' | 'mac' | 'linux' | 'unknown';
}

NetworkInfo

ts
interface NetworkInfo {
  online: boolean;
  type?: string;
  downlink?: number;
  rtt?: number;
  effectiveType?: string;
}