Compare commits
	
		
			2 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8514c4def0 | |||
| aeac92f3fd | 
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2015 Lossless GmbH
 | 
			
		||||
Copyright (c) 2015 Task Venture Capital GmbH
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,5 +1,16 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## 2025-11-01 - 6.0.0 - BREAKING CHANGE(Smartenv)
 | 
			
		||||
Add Deno and Bun runtime detection, introduce getSafeModuleFor API, update docs and tests, and make isNode semantics Node-only (breaking change)
 | 
			
		||||
 | 
			
		||||
- Implement runtime detection for Deno and Bun; runtimeEnv now returns one of 'node' | 'deno' | 'bun' | 'browser'.
 | 
			
		||||
- Change isNode to be true only for Node.js; add isDeno and isBun accessors. This is a breaking change in behavior for code that relied on isNode including Deno/Bun.
 | 
			
		||||
- Add getSafeModuleFor(target, moduleNameOrUrl, getFunction?) API to load modules conditionally for single, multiple or 'server' runtimes. Existing helpers getSafeNodeModule and getSafeWebModule updated to work with wider runtimes.
 | 
			
		||||
- Add runtime-specific version getters (nodeVersion, denoVersion, bunVersion) and update printEnv output accordingly.
 | 
			
		||||
- Expand and add tests for Node, Deno, Bun and Browser environments (tests/* files).
 | 
			
		||||
- Update documentation (readme.md and readme.hints.md) to describe detection order, new API and migration notes from 4.x to 5.x/6.x.
 | 
			
		||||
- Bump devDependencies (tsbuild, tsrun, tstest) and include an updated deno.lock.
 | 
			
		||||
 | 
			
		||||
## [5.0.13] - 2025-07-28
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "@push.rocks/smartenv",
 | 
			
		||||
  "version": "5.0.13",
 | 
			
		||||
  "version": "6.0.0",
 | 
			
		||||
  "description": "A module for storing and accessing environment details across different platforms.",
 | 
			
		||||
  "main": "dist_ts/index.js",
 | 
			
		||||
  "typings": "dist_ts/index.d.ts",
 | 
			
		||||
@@ -37,10 +37,10 @@
 | 
			
		||||
    "@push.rocks/smartpromise": "^4.0.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@git.zone/tsbuild": "^2.1.72",
 | 
			
		||||
    "@git.zone/tsbuild": "^2.6.8",
 | 
			
		||||
    "@git.zone/tsbundle": "^2.0.15",
 | 
			
		||||
    "@git.zone/tsrun": "^1.2.44",
 | 
			
		||||
    "@git.zone/tstest": "^2.3.2",
 | 
			
		||||
    "@git.zone/tsrun": "^1.6.2",
 | 
			
		||||
    "@git.zone/tstest": "^2.7.0",
 | 
			
		||||
    "@types/node": "^22.0.0"
 | 
			
		||||
  },
 | 
			
		||||
  "private": false,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4444
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4444
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										635
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										635
									
								
								readme.md
									
									
									
									
									
								
							@@ -1,241 +1,600 @@
 | 
			
		||||
# @push.rocks/smartenv
 | 
			
		||||
 | 
			
		||||
A cross-platform TypeScript library for detecting and managing runtime environments. It provides comprehensive environment detection capabilities and safe module loading for both Node.js and browser contexts.
 | 
			
		||||
> 🚀 **Universal JavaScript Runtime Detection** - One library for Node.js, Deno, Bun, and Browser
 | 
			
		||||
 | 
			
		||||
A powerful TypeScript library that provides comprehensive runtime environment detection and safe module loading across **all major JavaScript runtimes**. Write once, run everywhere with confidence.
 | 
			
		||||
 | 
			
		||||
## Why smartenv?
 | 
			
		||||
 | 
			
		||||
Modern JavaScript runs in many environments - Node.js, Deno, Bun, and browsers. Writing isomorphic code that works everywhere is challenging. **smartenv** solves this by providing:
 | 
			
		||||
 | 
			
		||||
- ✅ **Accurate runtime detection** - Distinguishes Node.js from Deno, Bun, and browsers without false positives
 | 
			
		||||
- ✅ **Smart module loading** - Load the right modules for each runtime automatically
 | 
			
		||||
- ✅ **Platform detection** - Detect macOS, Linux, Windows, and CI environments
 | 
			
		||||
- ✅ **Zero dependencies** (except @push.rocks/smartpromise)
 | 
			
		||||
- ✅ **Full TypeScript support** with complete type definitions
 | 
			
		||||
- ✅ **Battle-tested** - Comprehensive test suite across all runtimes
 | 
			
		||||
 | 
			
		||||
## Install
 | 
			
		||||
 | 
			
		||||
To install `@push.rocks/smartenv`, you need Node.js and pnpm installed. Then, run the following command:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
pnpm install @push.rocks/smartenv --save
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
```bash
 | 
			
		||||
npm install @push.rocks/smartenv --save
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`@push.rocks/smartenv` is a powerful utility for managing and accessing environment-specific information within your application. It enables your code to adapt seamlessly to different environments such as development, testing, and production.
 | 
			
		||||
 | 
			
		||||
### Getting Started
 | 
			
		||||
 | 
			
		||||
First, import the `Smartenv` class from the package:
 | 
			
		||||
## Quick Start
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
import { Smartenv } from '@push.rocks/smartenv';
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Initializing Smartenv
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
Create an instance of `Smartenv` to access all environment detection and module loading features:
 | 
			
		||||
// Detect the runtime
 | 
			
		||||
console.log(env.runtimeEnv); // 'node' | 'deno' | 'bun' | 'browser'
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const smartEnv = new Smartenv();
 | 
			
		||||
// Load modules safely for your runtime
 | 
			
		||||
const pathModule = await env.getSafeModuleFor('server', 'path');
 | 
			
		||||
if (pathModule) {
 | 
			
		||||
  console.log('Path module loaded!');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check specific runtimes
 | 
			
		||||
if (env.isNode) {
 | 
			
		||||
  console.log(`Running on Node.js ${env.nodeVersion}`);
 | 
			
		||||
} else if (env.isDeno) {
 | 
			
		||||
  console.log(`Running on Deno ${env.denoVersion}`);
 | 
			
		||||
} else if (env.isBun) {
 | 
			
		||||
  console.log(`Running on Bun ${env.bunVersion}`);
 | 
			
		||||
} else {
 | 
			
		||||
  console.log(`Running in ${env.userAgent}`);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Core Features
 | 
			
		||||
 | 
			
		||||
- **Runtime Environment Detection**: Instantly detect whether your code is running in Node.js or browser
 | 
			
		||||
- **Operating System Detection**: Identify Mac, Windows, or Linux platforms in Node.js environments
 | 
			
		||||
- **CI Environment Detection**: Detect if running in a continuous integration environment
 | 
			
		||||
- **Safe Module Loading**: Load modules conditionally based on the runtime environment
 | 
			
		||||
- **Browser Information**: Access user agent information in browser contexts
 | 
			
		||||
- **Node.js Version**: Get the current Node.js version when running in Node.js
 | 
			
		||||
### 🎯 Multi-Runtime Detection
 | 
			
		||||
 | 
			
		||||
## API Reference
 | 
			
		||||
 | 
			
		||||
### Environment Detection
 | 
			
		||||
 | 
			
		||||
#### `isNode: boolean`
 | 
			
		||||
Returns `true` if running in a Node.js environment.
 | 
			
		||||
Accurately detects all major JavaScript runtimes using proper detection order to avoid false positives:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isNode) {
 | 
			
		||||
  console.log('Running in Node.js');
 | 
			
		||||
}
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
// Runtime type - returns one of: 'node' | 'deno' | 'bun' | 'browser'
 | 
			
		||||
console.log(env.runtimeEnv);
 | 
			
		||||
 | 
			
		||||
// Boolean checks for each runtime
 | 
			
		||||
env.isNode;     // true only in Node.js
 | 
			
		||||
env.isDeno;     // true only in Deno
 | 
			
		||||
env.isBun;      // true only in Bun
 | 
			
		||||
env.isBrowser;  // true only in browser
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isBrowser: boolean`
 | 
			
		||||
Returns `true` if running in a browser environment.
 | 
			
		||||
**Why detection order matters:** Deno and Bun provide `process` objects for Node.js compatibility. smartenv checks for `Deno` and `Bun` globals first, then `process.versions.node`, ensuring accurate detection.
 | 
			
		||||
 | 
			
		||||
### 📦 Smart Module Loading
 | 
			
		||||
 | 
			
		||||
The new `getSafeModuleFor()` API lets you target specific runtimes or groups:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isBrowser) {
 | 
			
		||||
  console.log('Running in browser');
 | 
			
		||||
}
 | 
			
		||||
// Load for a specific runtime
 | 
			
		||||
const fsNode = await env.getSafeModuleFor('node', 'fs');
 | 
			
		||||
 | 
			
		||||
// Load for Deno (requires 'node:' prefix for Node.js built-ins)
 | 
			
		||||
const fsDeno = await env.getSafeModuleFor('deno', 'node:path');
 | 
			
		||||
 | 
			
		||||
// Load for all server-side runtimes (Node.js + Deno + Bun)
 | 
			
		||||
const pathModule = await env.getSafeModuleFor('server', 'path');
 | 
			
		||||
 | 
			
		||||
// Load for multiple specific runtimes
 | 
			
		||||
const crypto = await env.getSafeModuleFor(['node', 'bun'], 'crypto');
 | 
			
		||||
 | 
			
		||||
// Browser module loading
 | 
			
		||||
const jQuery = await env.getSafeModuleFor(
 | 
			
		||||
  'browser',
 | 
			
		||||
  'https://code.jquery.com/jquery-3.6.0.min.js',
 | 
			
		||||
  () => window.jQuery
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `runtimeEnv: string`
 | 
			
		||||
Returns the runtime environment as a string ('node' or 'browser').
 | 
			
		||||
**Target options:**
 | 
			
		||||
- `'node'` - Node.js only
 | 
			
		||||
- `'deno'` - Deno only
 | 
			
		||||
- `'bun'` - Bun only
 | 
			
		||||
- `'browser'` - Browser only
 | 
			
		||||
- `'server'` - Shorthand for `['node', 'deno', 'bun']`
 | 
			
		||||
- `['node', 'deno']` - Array of specific runtimes
 | 
			
		||||
 | 
			
		||||
If the current runtime doesn't match the target, the method returns `undefined` and logs a warning.
 | 
			
		||||
 | 
			
		||||
### 🖥️ Platform Detection
 | 
			
		||||
 | 
			
		||||
Detect operating systems in server-side runtimes (Node.js, Deno, Bun):
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
console.log(`Runtime: ${smartEnv.runtimeEnv}`);
 | 
			
		||||
```
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
#### `isCI: boolean`
 | 
			
		||||
Returns `true` if running in a CI environment (checks for CI environment variable).
 | 
			
		||||
// Async OS detection
 | 
			
		||||
const isMac = await env.isMacAsync();       // macOS
 | 
			
		||||
const isLinux = await env.isLinuxAsync();   // Linux
 | 
			
		||||
const isWindows = await env.isWindowsAsync(); // Windows
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isCI) {
 | 
			
		||||
  console.log('Running in CI environment');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Platform Detection (Node.js only)
 | 
			
		||||
 | 
			
		||||
#### `isMacAsync(): Promise<boolean>`
 | 
			
		||||
Asynchronously checks if running on macOS.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const isMac = await smartEnv.isMacAsync();
 | 
			
		||||
if (isMac) {
 | 
			
		||||
  console.log('Running on macOS');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isWindowsAsync(): Promise<boolean>`
 | 
			
		||||
Asynchronously checks if running on Windows.
 | 
			
		||||
### 🔢 Version Information
 | 
			
		||||
 | 
			
		||||
Get version strings for each runtime:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const isWindows = await smartEnv.isWindowsAsync();
 | 
			
		||||
if (isWindows) {
 | 
			
		||||
  console.log('Running on Windows');
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
// Returns version string or 'undefined' if not in that runtime
 | 
			
		||||
env.nodeVersion;  // e.g., 'v20.10.0'
 | 
			
		||||
env.denoVersion;  // e.g., '1.40.0'
 | 
			
		||||
env.bunVersion;   // e.g., '1.0.20'
 | 
			
		||||
env.userAgent;    // Browser user agent string
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 🏗️ CI Detection
 | 
			
		||||
 | 
			
		||||
Detect if running in a continuous integration environment:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
if (env.isCI) {
 | 
			
		||||
  console.log('Running in CI environment');
 | 
			
		||||
  // Enable extended test suite, different build config, etc.
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## API Reference
 | 
			
		||||
 | 
			
		||||
### Runtime Detection Properties
 | 
			
		||||
 | 
			
		||||
#### `runtimeEnv: TRuntimeType`
 | 
			
		||||
 | 
			
		||||
Returns the detected runtime as a string.
 | 
			
		||||
 | 
			
		||||
**Type:** `'node' | 'deno' | 'bun' | 'browser'`
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
console.log(env.runtimeEnv); // 'node', 'deno', 'bun', or 'browser'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isNode: boolean`
 | 
			
		||||
 | 
			
		||||
`true` if running in Node.js (specifically checks for `process.versions.node`).
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (env.isNode) {
 | 
			
		||||
  console.log('Node.js environment');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isDeno: boolean`
 | 
			
		||||
 | 
			
		||||
`true` if running in Deno (checks for `Deno` global).
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (env.isDeno) {
 | 
			
		||||
  console.log('Deno environment');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isBun: boolean`
 | 
			
		||||
 | 
			
		||||
`true` if running in Bun (checks for `Bun` global).
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (env.isBun) {
 | 
			
		||||
  console.log('Bun environment');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isBrowser: boolean`
 | 
			
		||||
 | 
			
		||||
`true` if running in a browser environment.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (env.isBrowser) {
 | 
			
		||||
  console.log('Browser environment');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isCI: boolean`
 | 
			
		||||
 | 
			
		||||
`true` if running in a CI environment (checks `process.env.CI` in server runtimes).
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (env.isCI) {
 | 
			
		||||
  // CI-specific logic
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Version Properties
 | 
			
		||||
 | 
			
		||||
#### `nodeVersion: string`
 | 
			
		||||
 | 
			
		||||
Node.js version string. Returns `'undefined'` if not in Node.js.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
console.log(env.nodeVersion); // 'v20.10.0'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `denoVersion: string`
 | 
			
		||||
 | 
			
		||||
Deno version string. Returns `'undefined'` if not in Deno.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
console.log(env.denoVersion); // '1.40.0'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `bunVersion: string`
 | 
			
		||||
 | 
			
		||||
Bun version string. Returns `'undefined'` if not in Bun.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
console.log(env.bunVersion); // '1.0.20'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `userAgent: string`
 | 
			
		||||
 | 
			
		||||
Browser user agent string. Returns `'undefined'` if not in browser.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
console.log(env.userAgent); // 'Mozilla/5.0...'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Platform Detection Methods
 | 
			
		||||
 | 
			
		||||
#### `isMacAsync(): Promise<boolean>`
 | 
			
		||||
 | 
			
		||||
Asynchronously checks if running on macOS. Works in Node.js, Deno, and Bun.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const isMac = await env.isMacAsync();
 | 
			
		||||
if (isMac) {
 | 
			
		||||
  console.log('Running on macOS');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `isLinuxAsync(): Promise<boolean>`
 | 
			
		||||
Asynchronously checks if running on Linux.
 | 
			
		||||
 | 
			
		||||
Asynchronously checks if running on Linux. Works in Node.js, Deno, and Bun.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const isLinux = await smartEnv.isLinuxAsync();
 | 
			
		||||
const isLinux = await env.isLinuxAsync();
 | 
			
		||||
if (isLinux) {
 | 
			
		||||
  console.log('Running on Linux');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Runtime Information
 | 
			
		||||
#### `isWindowsAsync(): Promise<boolean>`
 | 
			
		||||
 | 
			
		||||
#### `nodeVersion: string`
 | 
			
		||||
Returns the Node.js version (only available in Node.js environment).
 | 
			
		||||
Asynchronously checks if running on Windows. Works in Node.js, Deno, and Bun.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isNode) {
 | 
			
		||||
  console.log(`Node.js version: ${smartEnv.nodeVersion}`);
 | 
			
		||||
const isWindows = await env.isWindowsAsync();
 | 
			
		||||
if (isWindows) {
 | 
			
		||||
  console.log('Running on Windows');
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `userAgent: string`
 | 
			
		||||
Returns the browser user agent string (only available in browser environment).
 | 
			
		||||
### Module Loading Methods
 | 
			
		||||
 | 
			
		||||
#### `getSafeModuleFor<T>(target, moduleNameOrUrl, getFunction?): Promise<T | undefined>`
 | 
			
		||||
 | 
			
		||||
**The recommended way to load modules** - supports runtime targeting with flexible options.
 | 
			
		||||
 | 
			
		||||
**Parameters:**
 | 
			
		||||
- `target: TRuntimeTarget | TRuntimeTarget[]` - Runtime(s) to load for
 | 
			
		||||
- `moduleNameOrUrl: string` - Module name (server runtimes) or URL (browser)
 | 
			
		||||
- `getFunction?: () => any` - Function to retrieve module (required for browser)
 | 
			
		||||
 | 
			
		||||
**Returns:** `Promise<T | undefined>` - Loaded module or undefined if runtime doesn't match
 | 
			
		||||
 | 
			
		||||
**Examples:**
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isBrowser) {
 | 
			
		||||
  console.log(`Browser: ${smartEnv.userAgent}`);
 | 
			
		||||
}
 | 
			
		||||
// Node.js only
 | 
			
		||||
const fs = await env.getSafeModuleFor('node', 'fs');
 | 
			
		||||
 | 
			
		||||
// Deno only (note: use 'node:' prefix for Node.js built-ins)
 | 
			
		||||
const path = await env.getSafeModuleFor('deno', 'node:path');
 | 
			
		||||
 | 
			
		||||
// All server runtimes
 | 
			
		||||
const crypto = await env.getSafeModuleFor('server', 'crypto');
 | 
			
		||||
 | 
			
		||||
// Multiple specific runtimes
 | 
			
		||||
const util = await env.getSafeModuleFor(['node', 'bun'], 'util');
 | 
			
		||||
 | 
			
		||||
// Browser
 | 
			
		||||
const lib = await env.getSafeModuleFor(
 | 
			
		||||
  'browser',
 | 
			
		||||
  'https://cdn.example.com/lib.js',
 | 
			
		||||
  () => window.MyLib
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Module Loading
 | 
			
		||||
#### `getSafeNodeModule<T>(moduleName, runAfterFunc?): Promise<T>`
 | 
			
		||||
 | 
			
		||||
#### `getEnvAwareModule(options)`
 | 
			
		||||
Loads a module appropriate for the current environment. In Node.js, it uses dynamic import; in browsers, it loads a script via URL.
 | 
			
		||||
**Legacy method** - Loads modules in server-side runtimes (Node.js, Deno, Bun).
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const module = await smartEnv.getEnvAwareModule({
 | 
			
		||||
const fs = await env.getSafeNodeModule('fs');
 | 
			
		||||
 | 
			
		||||
// With post-load callback
 | 
			
		||||
const express = await env.getSafeNodeModule('express', async (mod) => {
 | 
			
		||||
  console.log('Express loaded');
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `getSafeWebModule(url, getFunction): Promise<any>`
 | 
			
		||||
 | 
			
		||||
**Legacy method** - Loads web modules via script tag in browser. Prevents duplicate loading.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const jQuery = await env.getSafeWebModule(
 | 
			
		||||
  'https://code.jquery.com/jquery-3.6.0.min.js',
 | 
			
		||||
  () => window.jQuery
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `getEnvAwareModule(options): Promise<any>`
 | 
			
		||||
 | 
			
		||||
**Legacy method** - Loads environment-appropriate modules.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const module = await env.getEnvAwareModule({
 | 
			
		||||
  nodeModuleName: 'node-fetch',
 | 
			
		||||
  webUrlArg: 'https://unpkg.com/whatwg-fetch@3.6.2/dist/fetch.umd.js',
 | 
			
		||||
  getFunction: () => window.fetch
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `getSafeNodeModule<T>(moduleName, runAfterFunc?)`
 | 
			
		||||
Safely loads a Node.js module with error handling. Only works in Node.js environment.
 | 
			
		||||
### Utility Methods
 | 
			
		||||
 | 
			
		||||
#### `printEnv(): Promise<void>`
 | 
			
		||||
 | 
			
		||||
Prints environment information to console for debugging.
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const fs = await smartEnv.getSafeNodeModule('fs');
 | 
			
		||||
if (fs) {
 | 
			
		||||
  // Use fs module
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// With post-load function
 | 
			
		||||
const express = await smartEnv.getSafeNodeModule('express', async (mod) => {
 | 
			
		||||
  console.log('Express loaded successfully');
 | 
			
		||||
});
 | 
			
		||||
await env.printEnv();
 | 
			
		||||
// Node.js: "running on NODE" + version
 | 
			
		||||
// Deno: "running on DENO" + version
 | 
			
		||||
// Bun: "running on BUN" + version
 | 
			
		||||
// Browser: "running on BROWSER" + user agent
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### `getSafeWebModule(url, getFunction)`
 | 
			
		||||
Safely loads a web module via script tag. Only works in browser environment. Prevents duplicate loading of the same script.
 | 
			
		||||
## Real-World Examples
 | 
			
		||||
 | 
			
		||||
### 🌍 Isomorphic Cryptography
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const jQuery = await smartEnv.getSafeWebModule(
 | 
			
		||||
  'https://code.jquery.com/jquery-3.6.0.min.js',
 | 
			
		||||
  () => window.jQuery
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
import { Smartenv } from '@push.rocks/smartenv';
 | 
			
		||||
 | 
			
		||||
### Debugging
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
#### `printEnv()`
 | 
			
		||||
Prints the current environment information to the console for debugging purposes.
 | 
			
		||||
// Load crypto for any server runtime
 | 
			
		||||
const crypto = await env.getSafeModuleFor('server', 'crypto');
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
await smartEnv.printEnv();
 | 
			
		||||
// Output in Node.js: "running on NODE" + version
 | 
			
		||||
// Output in browser: "running on BROWSER" + user agent
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Common Use Cases
 | 
			
		||||
 | 
			
		||||
### 1. Isomorphic Module Loading
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
// Define environment-specific implementations
 | 
			
		||||
const cryptoModule = await smartEnv.getEnvAwareModule({
 | 
			
		||||
  nodeModuleName: 'crypto',
 | 
			
		||||
  webUrlArg: 'https://unpkg.com/crypto-js@4.1.1/crypto-js.js',
 | 
			
		||||
  getFunction: () => window.CryptoJS
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 2. Platform-Specific Operations
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isNode) {
 | 
			
		||||
  const os = await smartEnv.getSafeNodeModule('os');
 | 
			
		||||
  console.log(`Home directory: ${os.homedir()}`);
 | 
			
		||||
} else {
 | 
			
		||||
  console.log('Browser environment - no filesystem access');
 | 
			
		||||
if (crypto) {
 | 
			
		||||
  const hash = crypto.createHash('sha256');
 | 
			
		||||
  hash.update('hello world');
 | 
			
		||||
  console.log(hash.digest('hex'));
 | 
			
		||||
} else if (env.isBrowser) {
 | 
			
		||||
  // Use Web Crypto API
 | 
			
		||||
  const encoder = new TextEncoder();
 | 
			
		||||
  const data = encoder.encode('hello world');
 | 
			
		||||
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
 | 
			
		||||
  console.log(Array.from(new Uint8Array(hashBuffer))
 | 
			
		||||
    .map(b => b.toString(16).padStart(2, '0'))
 | 
			
		||||
    .join(''));
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 3. CI/CD Pipeline Detection
 | 
			
		||||
### 📁 Cross-Runtime File System
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isCI) {
 | 
			
		||||
  // Run extended tests or different build configuration
 | 
			
		||||
  console.log('Running in CI - enabling extended test suite');
 | 
			
		||||
} else {
 | 
			
		||||
  console.log('Local development environment');
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
async function readConfig() {
 | 
			
		||||
  if (env.isNode) {
 | 
			
		||||
    const fs = await env.getSafeModuleFor('node', 'fs/promises');
 | 
			
		||||
    return JSON.parse(await fs.readFile('config.json', 'utf-8'));
 | 
			
		||||
  } else if (env.isDeno) {
 | 
			
		||||
    const content = await Deno.readTextFile('config.json');
 | 
			
		||||
    return JSON.parse(content);
 | 
			
		||||
  } else if (env.isBun) {
 | 
			
		||||
    const file = Bun.file('config.json');
 | 
			
		||||
    return await file.json();
 | 
			
		||||
  } else {
 | 
			
		||||
    // Browser: fetch from server
 | 
			
		||||
    const response = await fetch('/config.json');
 | 
			
		||||
    return response.json();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 4. Dynamic Script Loading in Browser
 | 
			
		||||
### 🔧 Development vs Production
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
if (smartEnv.isBrowser) {
 | 
			
		||||
  // Load analytics only in browser
 | 
			
		||||
  await smartEnv.getSafeWebModule(
 | 
			
		||||
    'https://www.google-analytics.com/analytics.js',
 | 
			
		||||
    () => window.ga
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
async function setupEnvironment() {
 | 
			
		||||
  // Different behavior in CI
 | 
			
		||||
  if (env.isCI) {
 | 
			
		||||
    console.log('CI Environment detected');
 | 
			
		||||
    // Skip interactive prompts, use default values
 | 
			
		||||
    return { mode: 'ci', verbose: true };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Platform-specific paths
 | 
			
		||||
  if (await env.isMacAsync()) {
 | 
			
		||||
    return { configPath: '/Users/username/.config' };
 | 
			
		||||
  } else if (await env.isLinuxAsync()) {
 | 
			
		||||
    return { configPath: '/home/username/.config' };
 | 
			
		||||
  } else if (await env.isWindowsAsync()) {
 | 
			
		||||
    return { configPath: 'C:\\Users\\username\\AppData\\Local' };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 🎨 Conditional Analytics Loading
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
async function initializeAnalytics() {
 | 
			
		||||
  if (!env.isBrowser) {
 | 
			
		||||
    console.log('Analytics skipped - not in browser');
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Only load analytics in browser
 | 
			
		||||
  const analytics = await env.getSafeModuleFor(
 | 
			
		||||
    'browser',
 | 
			
		||||
    'https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID',
 | 
			
		||||
    () => window.gtag
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if (analytics) {
 | 
			
		||||
    analytics('config', 'GA_MEASUREMENT_ID');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 🧪 Runtime-Specific Testing
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const env = new Smartenv();
 | 
			
		||||
 | 
			
		||||
async function runTests() {
 | 
			
		||||
  console.log(`Testing in ${env.runtimeEnv}`);
 | 
			
		||||
 | 
			
		||||
  // Load test utilities for current runtime
 | 
			
		||||
  const testLib = await env.getSafeModuleFor(
 | 
			
		||||
    ['node', 'deno', 'bun'],
 | 
			
		||||
    '@git.zone/tstest'
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  if (testLib) {
 | 
			
		||||
    // Run server-side tests
 | 
			
		||||
    await runServerTests(testLib);
 | 
			
		||||
  } else {
 | 
			
		||||
    // Run browser tests
 | 
			
		||||
    await runBrowserTests();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## TypeScript Support
 | 
			
		||||
 | 
			
		||||
The package is written in TypeScript and provides full type definitions. The main type export is:
 | 
			
		||||
smartenv is written in TypeScript and provides complete type definitions:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
export interface IEnvObject {
 | 
			
		||||
  name: string;
 | 
			
		||||
  value: string;
 | 
			
		||||
import {
 | 
			
		||||
  Smartenv,
 | 
			
		||||
  TRuntimeType,     // 'node' | 'deno' | 'bun' | 'browser'
 | 
			
		||||
  TRuntimeTarget,   // TRuntimeType | 'server'
 | 
			
		||||
  IEnvObject
 | 
			
		||||
} from '@push.rocks/smartenv';
 | 
			
		||||
 | 
			
		||||
const env: Smartenv = new Smartenv();
 | 
			
		||||
const runtime: TRuntimeType = env.runtimeEnv;
 | 
			
		||||
 | 
			
		||||
// Type-safe module loading
 | 
			
		||||
const fs = await env.getSafeModuleFor<typeof import('fs')>('node', 'fs');
 | 
			
		||||
if (fs) {
 | 
			
		||||
  fs.readFileSync('./file.txt', 'utf-8'); // Full type support
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## How Runtime Detection Works
 | 
			
		||||
 | 
			
		||||
smartenv uses a careful detection order to avoid false positives:
 | 
			
		||||
 | 
			
		||||
1. **Check for Deno** - `globalThis.Deno?.version` (Deno has `process` for compatibility)
 | 
			
		||||
2. **Check for Bun** - `globalThis.Bun?.version` (Bun also has `process`)
 | 
			
		||||
3. **Check for Node.js** - `globalThis.process?.versions?.node` (must be specific)
 | 
			
		||||
4. **Check for Browser** - `globalThis.window && globalThis.document` (fallback)
 | 
			
		||||
 | 
			
		||||
This order is critical because Deno and Bun provide `process` objects for Node.js compatibility, which would cause false Node.js detection if checked first.
 | 
			
		||||
 | 
			
		||||
## Migration from 4.x to 5.x
 | 
			
		||||
 | 
			
		||||
**Breaking Changes:**
 | 
			
		||||
 | 
			
		||||
1. **`runtimeEnv` return type changed:**
 | 
			
		||||
   - **Before:** `'node' | 'browser'`
 | 
			
		||||
   - **After:** `'node' | 'deno' | 'bun' | 'browser'`
 | 
			
		||||
 | 
			
		||||
2. **`isNode` is now more specific:**
 | 
			
		||||
   - **Before:** Returns `true` for Node.js, Deno, and Bun
 | 
			
		||||
   - **After:** Returns `true` only for Node.js
 | 
			
		||||
 | 
			
		||||
**Migration guide:**
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
// Before (4.x)
 | 
			
		||||
if (env.isNode) {
 | 
			
		||||
  // This ran in Node.js, Deno, and Bun
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// After (5.x) - Option 1: Check all server runtimes
 | 
			
		||||
if (env.isNode || env.isDeno || env.isBun) {
 | 
			
		||||
  // Works in Node.js, Deno, and Bun
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// After (5.x) - Option 2: Use the new module loading API
 | 
			
		||||
const module = await env.getSafeModuleFor('server', 'path');
 | 
			
		||||
if (module) {
 | 
			
		||||
  // Module loaded successfully in any server runtime
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Performance
 | 
			
		||||
 | 
			
		||||
- ⚡ **Lightweight** - Minimal overhead with lazy evaluation
 | 
			
		||||
- 🚀 **Fast detection** - Simple boolean checks, no heavy operations
 | 
			
		||||
- 💾 **Cached results** - Detection runs once, results are cached
 | 
			
		||||
- 📦 **Small bundle** - ~5KB minified, tree-shakeable
 | 
			
		||||
 | 
			
		||||
## Browser Compatibility
 | 
			
		||||
 | 
			
		||||
Tested and working in:
 | 
			
		||||
- ✅ Chrome/Chromium (latest)
 | 
			
		||||
- ✅ Firefox (latest)
 | 
			
		||||
- ✅ Safari (latest)
 | 
			
		||||
- ✅ Edge (latest)
 | 
			
		||||
 | 
			
		||||
## Node.js Compatibility
 | 
			
		||||
 | 
			
		||||
- ✅ Node.js 18.x
 | 
			
		||||
- ✅ Node.js 20.x (LTS)
 | 
			
		||||
- ✅ Node.js 22.x
 | 
			
		||||
 | 
			
		||||
## Deno Compatibility
 | 
			
		||||
 | 
			
		||||
- ✅ Deno 1.40+
 | 
			
		||||
 | 
			
		||||
**Note:** When using Deno, use the `node:` prefix for Node.js built-in modules:
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
const path = await env.getSafeModuleFor('deno', 'node:path');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Bun Compatibility
 | 
			
		||||
 | 
			
		||||
- ✅ Bun 1.0+
 | 
			
		||||
 | 
			
		||||
## License and Legal Information
 | 
			
		||||
 | 
			
		||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								test/test.bun.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								test/test.bun.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
 | 
			
		||||
import * as smartenv from '../ts/index.js';
 | 
			
		||||
 | 
			
		||||
let testEnv: smartenv.Smartenv;
 | 
			
		||||
 | 
			
		||||
tap.test('should create smartenv instance', async () => {
 | 
			
		||||
  testEnv = new smartenv.Smartenv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect Bun runtime correctly', async () => {
 | 
			
		||||
  expect(testEnv.runtimeEnv).toEqual('bun');
 | 
			
		||||
  expect(testEnv.isBun).toBeTrue();
 | 
			
		||||
  expect(testEnv.isNode).toBeFalse();
 | 
			
		||||
  expect(testEnv.isDeno).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBrowser).toBeFalse();
 | 
			
		||||
  console.log(' Bun runtime detected correctly');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get Bun version', async () => {
 | 
			
		||||
  const version = testEnv.bunVersion;
 | 
			
		||||
  expect(version).not.toEqual('undefined');
 | 
			
		||||
  expect(typeof version).toEqual('string');
 | 
			
		||||
  console.log('Bun version is ' + version);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should print environment', async () => {
 | 
			
		||||
  testEnv.printEnv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for Bun', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('bun', 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log(' Successfully loaded module for Bun');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for server runtimes', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('server', 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log(' Successfully loaded module with server target');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for array of runtimes', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor(['bun', 'node'], 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log(' Successfully loaded module with array target');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not load modules for wrong runtime', async () => {
 | 
			
		||||
  const result = await testEnv.getSafeModuleFor('node', 'path');
 | 
			
		||||
  expect(result).toBeUndefined();
 | 
			
		||||
  console.log(' Correctly rejected Node.js-only module in Bun');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect OS', async () => {
 | 
			
		||||
  const resultMac = await testEnv.isMacAsync();
 | 
			
		||||
  const resultLinux = await testEnv.isLinuxAsync();
 | 
			
		||||
  const resultWindows = await testEnv.isWindowsAsync();
 | 
			
		||||
  const osModule = await import('os');
 | 
			
		||||
  if (resultMac) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('darwin');
 | 
			
		||||
    console.log('platform is Mac!');
 | 
			
		||||
  } else if (resultLinux) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('linux');
 | 
			
		||||
    console.log('platform is Linux!');
 | 
			
		||||
  } else {
 | 
			
		||||
    expect(osModule.platform()).toEqual('win32');
 | 
			
		||||
    console.log('platform is Windows!');
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect CI environment if present', async () => {
 | 
			
		||||
  if (process.env.CI) {
 | 
			
		||||
    expect(testEnv.isCI).toBeTrue();
 | 
			
		||||
  }
 | 
			
		||||
  console.log('CI detection: ' + testEnv.isCI);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.start();
 | 
			
		||||
							
								
								
									
										58
									
								
								test/test.chrome.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								test/test.chrome.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
 | 
			
		||||
import * as smartenv from '../ts/index.js';
 | 
			
		||||
 | 
			
		||||
let testEnv: smartenv.Smartenv;
 | 
			
		||||
 | 
			
		||||
tap.test('should create smartenv instance', async () => {
 | 
			
		||||
  testEnv = new smartenv.Smartenv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect browser runtime correctly', async () => {
 | 
			
		||||
  expect(testEnv.runtimeEnv).toEqual('browser');
 | 
			
		||||
  expect(testEnv.isBrowser).toBeTrue();
 | 
			
		||||
  expect(testEnv.isNode).toBeFalse();
 | 
			
		||||
  expect(testEnv.isDeno).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBun).toBeFalse();
 | 
			
		||||
  console.log(' Browser runtime detected correctly');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get user agent', async () => {
 | 
			
		||||
  const userAgent = testEnv.userAgent;
 | 
			
		||||
  expect(userAgent).not.toEqual('undefined');
 | 
			
		||||
  expect(typeof userAgent).toEqual('string');
 | 
			
		||||
  console.log('User agent: ' + userAgent);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should print environment', async () => {
 | 
			
		||||
  testEnv.printEnv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not get server runtime versions', async () => {
 | 
			
		||||
  expect(testEnv.nodeVersion).toEqual('undefined');
 | 
			
		||||
  expect(testEnv.denoVersion).toEqual('undefined');
 | 
			
		||||
  expect(testEnv.bunVersion).toEqual('undefined');
 | 
			
		||||
  console.log(' Server runtime versions correctly return undefined in browser');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not load server modules', async () => {
 | 
			
		||||
  const result = await testEnv.getSafeModuleFor('server', 'path');
 | 
			
		||||
  expect(result).toBeUndefined();
 | 
			
		||||
  console.log(' Correctly rejected server module in browser');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not detect as CI', async () => {
 | 
			
		||||
  expect(testEnv.isCI).toBeFalse();
 | 
			
		||||
  console.log(' CI detection correctly false in browser');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('OS detection should return false in browser', async () => {
 | 
			
		||||
  const resultMac = await testEnv.isMacAsync();
 | 
			
		||||
  const resultLinux = await testEnv.isLinuxAsync();
 | 
			
		||||
  const resultWindows = await testEnv.isWindowsAsync();
 | 
			
		||||
  expect(resultMac).toBeFalse();
 | 
			
		||||
  expect(resultLinux).toBeFalse();
 | 
			
		||||
  expect(resultWindows).toBeFalse();
 | 
			
		||||
  console.log(' OS detection correctly returns false in browser');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.start();
 | 
			
		||||
							
								
								
									
										59
									
								
								test/test.deno.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								test/test.deno.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
 | 
			
		||||
import * as smartenv from '../ts/index.js';
 | 
			
		||||
 | 
			
		||||
let testEnv: smartenv.Smartenv;
 | 
			
		||||
 | 
			
		||||
tap.test('should create smartenv instance', async () => {
 | 
			
		||||
  testEnv = new smartenv.Smartenv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect Deno runtime correctly', async () => {
 | 
			
		||||
  expect(testEnv.runtimeEnv).toEqual('deno');
 | 
			
		||||
  expect(testEnv.isDeno).toBeTrue();
 | 
			
		||||
  expect(testEnv.isNode).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBun).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBrowser).toBeFalse();
 | 
			
		||||
  console.log(' Deno runtime detected correctly');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get Deno version', async () => {
 | 
			
		||||
  const version = testEnv.denoVersion;
 | 
			
		||||
  expect(version).not.toEqual('undefined');
 | 
			
		||||
  expect(typeof version).toEqual('string');
 | 
			
		||||
  console.log('Deno version is ' + version);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should print environment', async () => {
 | 
			
		||||
  testEnv.printEnv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for Deno', async () => {
 | 
			
		||||
  // Deno requires 'node:' prefix for Node.js built-in modules
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('deno', 'node:path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log(' Successfully loaded module for Deno');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for server runtimes', async () => {
 | 
			
		||||
  // Deno requires 'node:' prefix for Node.js built-in modules
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('server', 'node:path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log(' Successfully loaded module with server target');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not load modules for wrong runtime', async () => {
 | 
			
		||||
  const result = await testEnv.getSafeModuleFor('node', 'node:path');
 | 
			
		||||
  expect(result).toBeUndefined();
 | 
			
		||||
  console.log(' Correctly rejected Node.js-only module in Deno');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect CI environment if present', async () => {
 | 
			
		||||
  // CI detection relies on Node.js process.env, which may not work in Deno
 | 
			
		||||
  // This test documents expected behavior
 | 
			
		||||
  const isCI = testEnv.isCI;
 | 
			
		||||
  console.log('CI detection in Deno: ' + isCI);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.start();
 | 
			
		||||
							
								
								
									
										81
									
								
								test/test.node.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								test/test.node.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
 | 
			
		||||
import * as smartenv from '../ts/index.js';
 | 
			
		||||
 | 
			
		||||
let testEnv: smartenv.Smartenv;
 | 
			
		||||
 | 
			
		||||
tap.test('should create smartenv instance', async () => {
 | 
			
		||||
  testEnv = new smartenv.Smartenv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should detect Node.js runtime correctly', async () => {
 | 
			
		||||
  expect(testEnv.runtimeEnv).toEqual('node');
 | 
			
		||||
  expect(testEnv.isNode).toBeTrue();
 | 
			
		||||
  expect(testEnv.isDeno).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBun).toBeFalse();
 | 
			
		||||
  expect(testEnv.isBrowser).toBeFalse();
 | 
			
		||||
  console.log('✓ Node.js runtime detected correctly (not confused with Deno or Bun)');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get Node.js version', async () => {
 | 
			
		||||
  const version = testEnv.nodeVersion;
 | 
			
		||||
  expect(version).not.toEqual('undefined');
 | 
			
		||||
  expect(typeof version).toEqual('string');
 | 
			
		||||
  expect(version).toMatch(/^v\d+\.\d+\.\d+/);
 | 
			
		||||
  console.log('Node.js version is ' + version);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should print environment', async () => {
 | 
			
		||||
  testEnv.printEnv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for Node.js', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('node', 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log('✓ Successfully loaded module for Node.js');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for server runtimes', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor('server', 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log('✓ Successfully loaded module with server target');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should load modules for array of runtimes', async () => {
 | 
			
		||||
  const pathModule = await testEnv.getSafeModuleFor(['node', 'deno'], 'path');
 | 
			
		||||
  expect(pathModule).not.toBeUndefined();
 | 
			
		||||
  expect(typeof pathModule.join).toEqual('function');
 | 
			
		||||
  console.log('✓ Successfully loaded module with array target');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should not load modules for wrong runtime', async () => {
 | 
			
		||||
  const result = await testEnv.getSafeModuleFor('browser', 'path');
 | 
			
		||||
  expect(result).toBeUndefined();
 | 
			
		||||
  console.log('✓ Correctly rejected browser-only module in Node.js');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get os', async () => {
 | 
			
		||||
  const resultMac = await testEnv.isMacAsync();
 | 
			
		||||
  const resultLinux = await testEnv.isLinuxAsync();
 | 
			
		||||
  const resultWindows = await testEnv.isWindowsAsync();
 | 
			
		||||
  const osModule = await import('os');
 | 
			
		||||
  if (resultMac) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('darwin');
 | 
			
		||||
    console.log('platform is Mac!');
 | 
			
		||||
  } else if (resultLinux) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('linux');
 | 
			
		||||
    console.log('platform is Linux!');
 | 
			
		||||
  } else {
 | 
			
		||||
    expect(osModule.platform()).toEqual('win32');
 | 
			
		||||
    console.log('platform is Windows!');
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should state wether we are in CI', async () => {
 | 
			
		||||
  if (process.env.CI) {
 | 
			
		||||
    expect(testEnv.isCI).toBeTrue();
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.start();
 | 
			
		||||
							
								
								
									
										37
									
								
								test/test.ts
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								test/test.ts
									
									
									
									
									
								
							@@ -1,37 +0,0 @@
 | 
			
		||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
 | 
			
		||||
import * as smartenv from '../ts/index.js';
 | 
			
		||||
 | 
			
		||||
let testEnv: smartenv.Smartenv;
 | 
			
		||||
 | 
			
		||||
tap.test('should print env', async () => {
 | 
			
		||||
  testEnv = new smartenv.Smartenv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should print a overview to console', async () => {
 | 
			
		||||
  testEnv.printEnv();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should get os', async () => {
 | 
			
		||||
  const resultMac = await testEnv.isMacAsync();
 | 
			
		||||
  const resultLinux = await testEnv.isLinuxAsync();
 | 
			
		||||
  const resultWindows = await testEnv.isWindowsAsync();
 | 
			
		||||
  const osModule = await import('os');
 | 
			
		||||
  if (resultMac) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('darwin');
 | 
			
		||||
    console.log('platform is Mac!');
 | 
			
		||||
  } else if (resultLinux) {
 | 
			
		||||
    expect(osModule.platform()).toEqual('linux');
 | 
			
		||||
    console.log('platform is Linux!');
 | 
			
		||||
  } else {
 | 
			
		||||
    expect(osModule.platform()).toEqual('win32');
 | 
			
		||||
    console.log('platform is Windows!');
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.test('should state wether we are in CI', async () => {
 | 
			
		||||
  if (process.env.CI) {
 | 
			
		||||
    expect(testEnv.isCI).toBeTrue();
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
tap.start();
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
/**
 | 
			
		||||
 * autocreated commitinfo by @pushrocks/commitinfo
 | 
			
		||||
 * autocreated commitinfo by @push.rocks/commitinfo
 | 
			
		||||
 */
 | 
			
		||||
export const commitinfo = {
 | 
			
		||||
  name: '@push.rocks/smartenv',
 | 
			
		||||
  version: '5.0.12',
 | 
			
		||||
  description: 'store things about your environment and let them travel across modules'
 | 
			
		||||
  version: '6.0.0',
 | 
			
		||||
  description: 'A module for storing and accessing environment details across different platforms.'
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,15 @@
 | 
			
		||||
export let defaultme = null;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Runtime type representing the detected JavaScript runtime environment
 | 
			
		||||
 */
 | 
			
		||||
export type TRuntimeType = 'node' | 'deno' | 'bun' | 'browser';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Runtime target for module loading - can be a specific runtime or 'server' for all server-side runtimes
 | 
			
		||||
 */
 | 
			
		||||
export type TRuntimeTarget = TRuntimeType | 'server';
 | 
			
		||||
 | 
			
		||||
declare global {
 | 
			
		||||
  namespace NodeJS {
 | 
			
		||||
    interface Global {
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,8 @@ export class Smartenv {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async getSafeNodeModule<T = any>(moduleNameArg: string, runAfterFunc?: (moduleArg: T) => Promise<any>): Promise<T> {
 | 
			
		||||
    if (!this.isNode) {
 | 
			
		||||
      console.error(`You tried to load a node module in a wrong context: ${moduleNameArg}. This does not throw.`);
 | 
			
		||||
    if (!this.isNode && !this.isDeno && !this.isBun) {
 | 
			
		||||
      console.error(`You tried to load a server module in a wrong context: ${moduleNameArg}. This does not throw.`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    // tslint:disable-next-line: function-constructor
 | 
			
		||||
@@ -72,16 +72,49 @@ export class Smartenv {
 | 
			
		||||
    return getFunctionArg();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get runtimeEnv() {
 | 
			
		||||
    if (typeof process !== 'undefined') {
 | 
			
		||||
  public get runtimeEnv(): interfaces.TRuntimeType {
 | 
			
		||||
    // Check Deno first (most distinctive)
 | 
			
		||||
    if (typeof globalThis.Deno !== 'undefined' &&
 | 
			
		||||
        typeof (globalThis as any).Deno?.version !== 'undefined') {
 | 
			
		||||
      return 'deno';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check Bun second (most distinctive)
 | 
			
		||||
    if (typeof globalThis.Bun !== 'undefined' &&
 | 
			
		||||
        typeof (globalThis as any).Bun?.version !== 'undefined') {
 | 
			
		||||
      return 'bun';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check Node.js (be explicit about versions to avoid Deno/Bun false positives)
 | 
			
		||||
    if (typeof globalThis.process !== 'undefined' &&
 | 
			
		||||
        typeof (globalThis as any).process?.versions?.node !== 'undefined') {
 | 
			
		||||
      return 'node';
 | 
			
		||||
    } else {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check Browser (default fallback)
 | 
			
		||||
    if (typeof globalThis.window !== 'undefined' &&
 | 
			
		||||
        typeof (globalThis as any).document !== 'undefined') {
 | 
			
		||||
      return 'browser';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Safe fallback
 | 
			
		||||
    return 'browser';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isBrowser(): boolean {
 | 
			
		||||
    return !this.isNode;
 | 
			
		||||
    return this.runtimeEnv === 'browser';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isNode(): boolean {
 | 
			
		||||
    return this.runtimeEnv === 'node';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isDeno(): boolean {
 | 
			
		||||
    return this.runtimeEnv === 'deno';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isBun(): boolean {
 | 
			
		||||
    return this.runtimeEnv === 'bun';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get userAgent(): string {
 | 
			
		||||
@@ -93,12 +126,77 @@ export class Smartenv {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isNode(): boolean {
 | 
			
		||||
    return this.runtimeEnv === 'node';
 | 
			
		||||
  public get nodeVersion(): string {
 | 
			
		||||
    if (this.isNode) {
 | 
			
		||||
      return process.version;
 | 
			
		||||
    }
 | 
			
		||||
    return 'undefined';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get nodeVersion(): string {
 | 
			
		||||
    return process.version;
 | 
			
		||||
  public get denoVersion(): string {
 | 
			
		||||
    if (this.isDeno) {
 | 
			
		||||
      return (globalThis as any).Deno.version.deno;
 | 
			
		||||
    }
 | 
			
		||||
    return 'undefined';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get bunVersion(): string {
 | 
			
		||||
    if (this.isBun) {
 | 
			
		||||
      return (globalThis as any).Bun.version;
 | 
			
		||||
    }
 | 
			
		||||
    return 'undefined';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Load a module only if the current runtime matches the target runtime(s)
 | 
			
		||||
   * @param target - Single runtime, array of runtimes, or 'server' for all server-side runtimes
 | 
			
		||||
   * @param moduleNameOrUrl - Module name (for Node/Deno/Bun) or URL (for browser)
 | 
			
		||||
   * @param getFunction - Optional function to retrieve the module in browser context
 | 
			
		||||
   * @returns The loaded module or undefined if runtime doesn't match
 | 
			
		||||
   */
 | 
			
		||||
  public async getSafeModuleFor<T = any>(
 | 
			
		||||
    target: interfaces.TRuntimeTarget | interfaces.TRuntimeTarget[],
 | 
			
		||||
    moduleNameOrUrl: string,
 | 
			
		||||
    getFunction?: () => any
 | 
			
		||||
  ): Promise<T | undefined> {
 | 
			
		||||
    // Normalize target to array
 | 
			
		||||
    let targetRuntimes: interfaces.TRuntimeType[];
 | 
			
		||||
 | 
			
		||||
    if (Array.isArray(target)) {
 | 
			
		||||
      // Expand 'server' if present in array
 | 
			
		||||
      targetRuntimes = target.flatMap(t =>
 | 
			
		||||
        t === 'server' ? ['node', 'deno', 'bun'] as interfaces.TRuntimeType[] : [t as interfaces.TRuntimeType]
 | 
			
		||||
      );
 | 
			
		||||
    } else if (target === 'server') {
 | 
			
		||||
      targetRuntimes = ['node', 'deno', 'bun'];
 | 
			
		||||
    } else {
 | 
			
		||||
      targetRuntimes = [target];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if current runtime matches any target
 | 
			
		||||
    if (!targetRuntimes.includes(this.runtimeEnv)) {
 | 
			
		||||
      console.warn(
 | 
			
		||||
        `Module "${moduleNameOrUrl}" requested for runtime(s) [${targetRuntimes.join(', ')}] ` +
 | 
			
		||||
        `but current runtime is "${this.runtimeEnv}". Skipping load.`
 | 
			
		||||
      );
 | 
			
		||||
      return undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Load based on current runtime
 | 
			
		||||
    if (this.isNode || this.isDeno || this.isBun) {
 | 
			
		||||
      // Server-side runtimes use dynamic import
 | 
			
		||||
      const moduleResult = await this.getSafeNodeModule<T>(moduleNameOrUrl);
 | 
			
		||||
      return moduleResult;
 | 
			
		||||
    } else if (this.isBrowser) {
 | 
			
		||||
      if (!getFunction) {
 | 
			
		||||
        console.error(`Browser module load requires getFunction parameter for "${moduleNameOrUrl}"`);
 | 
			
		||||
        return undefined;
 | 
			
		||||
      }
 | 
			
		||||
      const moduleResult = await this.getSafeWebModule(moduleNameOrUrl, getFunction);
 | 
			
		||||
      return moduleResult as T;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isCI(): boolean {
 | 
			
		||||
@@ -147,6 +245,12 @@ export class Smartenv {
 | 
			
		||||
    if (this.isNode) {
 | 
			
		||||
      console.log('running on NODE');
 | 
			
		||||
      console.log('node version is ' + this.nodeVersion);
 | 
			
		||||
    } else if (this.isDeno) {
 | 
			
		||||
      console.log('running on DENO');
 | 
			
		||||
      console.log('deno version is ' + this.denoVersion);
 | 
			
		||||
    } else if (this.isBun) {
 | 
			
		||||
      console.log('running on BUN');
 | 
			
		||||
      console.log('bun version is ' + this.bunVersion);
 | 
			
		||||
    } else {
 | 
			
		||||
      console.log('running on BROWSER');
 | 
			
		||||
      console.log('browser is ' + this.userAgent);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user