Files
smartenv/readme.hints.md

3.4 KiB

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:

// 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