/** * ThreadTS Universal - Platform Detection Utilities */ import { Platform } from '../types'; // Global environment type definitions interface NodeGlobal { process?: { versions?: { node?: string; }; memoryUsage?: () => { rss: number; heapTotal: number; heapUsed: number; external: number; arrayBuffers: number; }; }; require?: NodeRequire; } interface DenoGlobal { Deno?: { version: { deno: string; }; }; navigator?: { hardwareConcurrency?: number; }; } interface BunGlobal { Bun?: { version: string; }; navigator?: { hardwareConcurrency?: number; }; } interface BrowserGlobal { navigator?: { hardwareConcurrency?: number; }; performance?: { memory?: { usedJSHeapSize: number; totalJSHeapSize: number; jsHeapSizeLimit: number; }; now(): number; }; } type GlobalEnvironment = NodeGlobal & DenoGlobal & BunGlobal & BrowserGlobal; /** * Detects the current JavaScript runtime platform */ export function detectPlatform(): Platform { // Browser detection if (typeof window !== 'undefined' && typeof window.document !== 'undefined') { return 'browser'; } const env = globalThis as unknown as GlobalEnvironment; // Node.js detection if ( typeof env.process !== 'undefined' && env.process.versions && env.process.versions.node ) { return 'node'; } // Deno detection if (typeof env.Deno !== 'undefined') { return 'deno'; } // Bun detection if (typeof env.Bun !== 'undefined') { return 'bun'; } return 'unknown'; } /** * Checks if Worker Threads are supported in the current environment */ export function supportsWorkerThreads(): boolean { const platform = detectPlatform(); switch (platform) { case 'browser': return typeof Worker !== 'undefined'; case 'node': try { // Dynamic import for Node.js worker_threads const env = globalThis as unknown as GlobalEnvironment; const nodeRequire = env.require; if (nodeRequire) { nodeRequire('worker_threads'); return true; } return false; } catch { return false; } case 'deno': return typeof Worker !== 'undefined'; case 'bun': return typeof Worker !== 'undefined'; default: return false; } } /** * Checks if Transferable Objects are supported */ export function supportsTransferableObjects(): boolean { const platform = detectPlatform(); switch (platform) { case 'browser': return ( typeof ArrayBuffer !== 'undefined' && typeof MessageChannel !== 'undefined' ); case 'node': return true; // Node.js supports transferable objects in worker_threads case 'deno': return typeof ArrayBuffer !== 'undefined'; case 'bun': return typeof ArrayBuffer !== 'undefined'; default: return false; } } /** * Gets the optimal number of workers for the current platform */ export function getOptimalThreadCount(): number { const platform = detectPlatform(); switch (platform) { case 'browser': { const env = globalThis as unknown as GlobalEnvironment; return env.navigator?.hardwareConcurrency || 4; } case 'node': { try { const env = globalThis as unknown as GlobalEnvironment; const nodeRequire = env.require; if (nodeRequire) { const os = nodeRequire('os'); return os.cpus().length; } return 4; } catch { return 4; } } case 'deno': { const denoEnv = globalThis as unknown as GlobalEnvironment; return denoEnv.navigator?.hardwareConcurrency || 4; } case 'bun': { const bunEnv = globalThis as unknown as GlobalEnvironment; return bunEnv.navigator?.hardwareConcurrency || 4; } default: return 4; } } /** * Checks if the current environment supports OffscreenCanvas */ export function supportsOffscreenCanvas(): boolean { return typeof OffscreenCanvas !== 'undefined'; } /** * Checks if the current environment supports Web Locks API */ export function supportsWebLocks(): boolean { return typeof navigator !== 'undefined' && 'locks' in navigator; } /** * Gets platform-specific performance timestamp */ export function getHighResTimestamp(): number { const platform = detectPlatform(); switch (platform) { case 'browser': return performance.now(); case 'node': try { const env = globalThis as unknown as GlobalEnvironment; const nodeRequire = env.require; if (nodeRequire) { const { performance: nodePerf } = nodeRequire('perf_hooks'); return nodePerf.now(); } return Date.now(); } catch { return Date.now(); } case 'deno': return performance.now(); case 'bun': return performance.now(); default: return Date.now(); } } /** * Platform-specific memory usage information */ export interface MemoryInfo { used: number; total: number; available: number; } /** * Gets memory information for the current platform */ export function getMemoryInfo(): MemoryInfo | null { const platform = detectPlatform(); switch (platform) { case 'browser': if (typeof performance !== 'undefined' && 'memory' in performance) { const env = globalThis as unknown as GlobalEnvironment; const mem = env.performance?.memory; if (mem) { return { used: mem.usedJSHeapSize, total: mem.totalJSHeapSize, available: mem.jsHeapSizeLimit - mem.usedJSHeapSize, }; } } return null; case 'node': try { const env = globalThis as unknown as GlobalEnvironment; const nodeProcess = env.process; if (nodeProcess?.memoryUsage) { const mem = nodeProcess.memoryUsage(); return { used: mem.heapUsed, total: mem.heapTotal, available: mem.heapTotal - mem.heapUsed, }; } return null; } catch { return null; } case 'deno': if (typeof performance !== 'undefined' && 'memory' in performance) { const env = globalThis as unknown as GlobalEnvironment; const mem = env.performance?.memory; if (mem) { return { used: mem.usedJSHeapSize, total: mem.totalJSHeapSize, available: mem.jsHeapSizeLimit - mem.usedJSHeapSize, }; } } return null; default: return null; } } // Platform utilities class for easier access export class PlatformUtils { static detectPlatform = detectPlatform; static supportsWorkerThreads = supportsWorkerThreads; static supportsTransferableObjects = supportsTransferableObjects; static getOptimalWorkerCount = getOptimalThreadCount; static supportsOffscreenCanvas = supportsOffscreenCanvas; static supportsWebLocks = supportsWebLocks; static getHighResTimestamp = getHighResTimestamp; static getMemoryInfo = getMemoryInfo; }