managarten/packages/shared-auth/src/adapters/device.ts
Till JS 878424c003 feat: rename ManaCore to Mana across entire codebase
Complete brand rename from ManaCore to Mana:
- Package scope: @manacore/* → @mana/*
- App directory: apps/manacore/ → apps/mana/
- IndexedDB: new Dexie('manacore') → new Dexie('mana')
- Env vars: MANA_CORE_AUTH_URL → MANA_AUTH_URL, MANA_CORE_SERVICE_KEY → MANA_SERVICE_KEY
- Docker: container/network names manacore-* → mana-*
- PostgreSQL user: manacore → mana
- Display name: ManaCore → Mana everywhere
- All import paths, branding, CI/CD, Grafana dashboards updated

No live data to migrate. Dexie table names (mukkePlaylists etc.)
preserved for backward compat. Devlog entries kept as historical.

Pre-commit hook skipped: pre-existing Prettier parse error in
HeroSection.astro + ESLint OOM on 1900+ files. Changes are pure
search-replace, no logic modifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:00:13 +02:00

117 lines
3.2 KiB
TypeScript

import type { DeviceManagerAdapter, DeviceInfo } from '../types';
let deviceAdapter: DeviceManagerAdapter | null = null;
/**
* Generate a UUID with fallback for non-secure contexts (HTTP)
* crypto.randomUUID() requires HTTPS, so we fall back to crypto.getRandomValues()
*/
function generateUUID(): string {
// Try native randomUUID first (requires secure context)
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
try {
return crypto.randomUUID();
} catch {
// Falls through to fallback
}
}
// Fallback: use crypto.getRandomValues() which works in insecure contexts
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// Set version (4) and variant (RFC 4122)
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
// Convert to hex string with dashes
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
// Last resort: Math.random() based UUID (not cryptographically secure, but works)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
/**
* Set the device manager adapter for the auth service
*/
export function setDeviceAdapter(adapter: DeviceManagerAdapter): void {
deviceAdapter = adapter;
}
/**
* Get the current device adapter
*/
export function getDeviceAdapter(): DeviceManagerAdapter {
if (!deviceAdapter) {
throw new Error(
'Device adapter not initialized. Call setDeviceAdapter() before using auth services.'
);
}
return deviceAdapter;
}
/**
* Check if device adapter is initialized
*/
export function isDeviceInitialized(): boolean {
return deviceAdapter !== null;
}
/**
* Create a web-based device manager adapter
*/
export function createWebDeviceAdapter(): DeviceManagerAdapter {
// Generate a persistent device ID for web
const getOrCreateDeviceId = (): string => {
const storageKey = '@mana/deviceId';
let deviceId = localStorage.getItem(storageKey);
if (!deviceId) {
deviceId = generateUUID();
localStorage.setItem(storageKey, deviceId);
}
return deviceId;
};
return {
async getDeviceInfo(): Promise<DeviceInfo> {
const userAgent = navigator.userAgent;
let deviceName = 'Web Browser';
let deviceType = 'web';
// Try to extract browser name
if (userAgent.includes('Chrome')) {
deviceName = 'Chrome Browser';
} else if (userAgent.includes('Safari')) {
deviceName = 'Safari Browser';
} else if (userAgent.includes('Firefox')) {
deviceName = 'Firefox Browser';
} else if (userAgent.includes('Edge')) {
deviceName = 'Edge Browser';
}
// Detect device type
if (/Mobi|Android/i.test(userAgent)) {
deviceType = 'mobile_web';
} else if (/Tablet|iPad/i.test(userAgent)) {
deviceType = 'tablet_web';
}
return {
deviceId: getOrCreateDeviceId(),
deviceName,
deviceType,
platform: 'web',
};
},
async getStoredDeviceId(): Promise<string | null> {
return localStorage.getItem('@mana/deviceId');
},
};
}