BREAKING CHANGE(Smartenv): Add Deno and Bun runtime detection, introduce getSafeModuleFor API, update docs and tests, and make isNode semantics Node-only (breaking change)
This commit is contained in:
@@ -4,20 +4,76 @@
|
||||
- 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
|
||||
- Runtime detection based on checking if `process` is defined
|
||||
- Dynamic module loading using Function constructor for Node.js modules
|
||||
- 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 Node.js 'os' module loaded dynamically
|
||||
- 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
|
||||
- Test file demonstrates OS detection and CI environment detection
|
||||
- Tests can run in both Node.js and browser environments
|
||||
- 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 both Node.js and browser contexts
|
||||
- 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
|
||||
Reference in New Issue
Block a user