# SmartEnv Hints ## Architecture Overview - Single main class `Smartenv` that provides all functionality - Uses dependency injection pattern with plugins imported from smartenv.plugins.ts - Utilizes @push.rocks/smartpromise for async operations - **BREAKING CHANGE**: `runtimeEnv` now returns `'node' | 'deno' | 'bun' | 'browser'` (previously only 'node' | 'browser') ## Runtime Detection System ### Detection Order (Critical!) The order matters to avoid false positives: 1. **Deno** - Check `globalThis.Deno?.version` first (Deno has a `process` object for compatibility) 2. **Bun** - Check `globalThis.Bun?.version` second (Bun also has a `process` object) 3. **Node.js** - Check `globalThis.process?.versions?.node` third (must be specific to avoid Deno/Bun) 4. **Browser** - Check `globalThis.window && globalThis.document` as fallback ### Runtime Properties - `runtimeEnv: TRuntimeType` - Returns 'node' | 'deno' | 'bun' | 'browser' - `isNode: boolean` - True only for Node.js (excludes Deno and Bun) - `isDeno: boolean` - True only for Deno runtime - `isBun: boolean` - True only for Bun runtime - `isBrowser: boolean` - True only for browser environment ### Version Getters - `nodeVersion: string` - Node.js version (returns 'undefined' in other runtimes) - `denoVersion: string` - Deno version (returns 'undefined' in other runtimes) - `bunVersion: string` - Bun version (returns 'undefined' in other runtimes) ## Module Loading API ### New: getSafeModuleFor() Flexible module loading that supports runtime targeting: ```typescript // Load for specific runtime await env.getSafeModuleFor('node', 'path') // Load for multiple runtimes await env.getSafeModuleFor(['node', 'deno'], 'path') // Load for all server-side runtimes (shorthand for ['node', 'deno', 'bun']) await env.getSafeModuleFor('server', 'path') // Browser loading requires getFunction await env.getSafeModuleFor('browser', 'url', () => window.someLibrary) ``` **Parameters:** - `target: TRuntimeTarget | TRuntimeTarget[]` - Runtime(s) to load for - `moduleNameOrUrl: string` - Module name or URL - `getFunction?: () => any` - Required for browser module loading **Returns:** Module or `undefined` if runtime doesn't match ### Legacy Methods (Still Supported) - `getSafeNodeModule()` - Now works for Node.js, Deno, and Bun - `getSafeWebModule()` - Browser-only module loading ## Key Implementation Details - Dynamic module loading using Function constructor for server-side modules - Script tag injection for browser module loading with duplicate prevention - OS detection uses the native 'os' module loaded dynamically (works in Node.js, Deno, Bun) - All detection uses `globalThis` for robustness across environments ## Testing Approach - Tests use @git.zone/tstest with tap-based testing across all runtimes - `test.node.ts` - Node.js specific tests, verifies it's not confused with Deno/Bun - `test.deno.ts` - Deno runtime tests - `test.bun.ts` - Bun runtime tests - `test.chrome.ts` - Browser environment tests - Each test file verifies proper runtime detection and module loading ## Important Notes - The `getSafeNodeModule` uses dynamic import via Function constructor to avoid bundler issues - Browser module loading tracks loaded scripts to prevent duplicate loads - All OS detection methods are async and return false in browser environments - The package is isomorphic and designed for use in all four runtime contexts - Runtime detection checks globals in specific order to avoid false positives from compatibility layers