Files
smartenv/readme.hints.md

79 lines
3.4 KiB
Markdown

# 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