/* * This file is part of the xPack project (http://xpack.github.io). * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software * for any purpose is hereby granted, under the terms of the MIT license. * * If a copy of the license was not distributed with this file, it can * be obtained from https://opensource.org/license/mit. */ // ---------------------------------------------------------------------------- /** * Platform information structure for runtime environment detection. * * @remarks * This interface encapsulates operating system and architecture information * used throughout the xPack library for platform-specific behaviour, * path filtering, and binary distribution selection. */ export interface PlatformInfo { /** * The operating system platform identifier. * * @remarks * Common values include: * * * * Corresponds to process.platform from Node.js. */ platform: string /** * The CPU architecture identifier. * * @remarks * Common values include: * * * * Corresponds to process.arch from Node.js. */ arch: string } /** * Options for platform information retrieval. * * @remarks * This interface defines configuration options that control how platform * information is retrieved and processed, particularly for architecture * coercion scenarios. */ export interface PlatformInfoOptions { /** * Whether to coerce 64-bit architectures to their 32-bit equivalents. * * @remarks * When true, applies the following architecture mappings: * * * * This is useful for backward compatibility scenarios where only 32-bit * binaries are available but can run on 64-bit systems. * * @defaultValue `false` */ doForce32bit?: boolean } // ============================================================================ /** * Platform detection service for runtime environment identification. * * @remarks * This class encapsulates platform and architecture detection logic, * providing a mockable abstraction over Node.js process properties. * It enables testable platform-specific behaviour without requiring * execution on multiple operating systems or architectures. * * Key features: * *
    *
  1. Dependency injection: Accepts a custom process object via * constructor, enabling test environments to inject mock process * implementations.
  2. *
  3. Architecture coercion: Provides optional 64-bit to 32-bit * architecture mapping for backward compatibility scenarios.
  4. *
  5. Consistent interface: Returns standardised * {@link PlatformInfo} objects for use throughout the xPack library.
  6. *
* * This abstraction eliminates direct process.platform and * process.arch access in business logic, making platform-specific * code paths testable via mocked platform information. * * @example * Default usage with actual runtime platform: * ```typescript * const detector = new PlatformDetector() * const info = detector.getPlatformInfo() * console.log(info.platform) // 'darwin', 'linux', or 'win32' * console.log(info.arch) // 'x64', 'arm64', etc. * ``` * * @example * Testing with mocked platform: * ```typescript * const mockProcess = { * platform: 'darwin', * arch: 'arm64' * } as NodeJS.Process * * const detector = new PlatformDetector(mockProcess) * const info = detector.getPlatformInfo({ doForce32bit: true }) * // info.platform === 'darwin' * // info.arch === 'arm' (coerced from arm64) * ``` */ export class PlatformDetector { // -------------------------------------------------------------------------- // Private Members. /** * The Node.js process object for accessing platform information. */ private readonly process: NodeJS.Process // -------------------------------------------------------------------------- // Constructor. /** * Constructs a platform detector instance. * * @remarks * This constructor accepts an optional process object parameter, enabling * dependency injection for testing scenarios. When no process object is * provided, the global Node.js process is used automatically. * * The injected process object must implement the platform and * arch properties from the NodeJS.Process * interface. * * @param _process - The Node.js process object providing platform and * architecture information. Defaults to the global process * object. */ constructor(_process: NodeJS.Process = globalThis.process) { this.process = _process } // -------------------------------------------------------------------------- // Public Methods. /** * Retrieves current platform and architecture information. * * @remarks * This method returns a {@link PlatformInfo} object containing the * operating system platform and CPU architecture. When the * doForce32bit option is enabled, 64-bit architectures * are coerced to their 32-bit equivalents. * * Architecture coercion rules (when doForce32bit is * true): * * * * This coercion is useful for backward compatibility scenarios where * only 32-bit binaries are available but can run on 64-bit systems via * compatibility layers. * * The platform identifier is never modified and always reflects the actual * operating system (darwin, linux, * win32). * * @param options - Configuration options controlling platform information * retrieval. * @returns Platform and architecture information. */ getPlatformInfo(options: PlatformInfoOptions = {}): PlatformInfo { const { doForce32bit = false } = options let arch = this.process.arch if (doForce32bit) { // https://nodejs.org/docs/latest/api/process.html#processarch if (arch === 'x64') { arch = 'ia32' } else if (arch === 'arm64') { arch = 'arm' } } return { platform: this.process.platform, arch, } } /** * Checks whether the current platform is Windows. * * @remarks * This convenience method provides a simple boolean check for Windows * platform detection, commonly used for path handling and command * formatting decisions. * * Equivalent to checking platform === 'win32'. * * @returns true if running on Windows, * false otherwise. */ isWindows(): boolean { return this.process.platform === 'win32' } } // ----------------------------------------------------------------------------