/* * 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. */ // ---------------------------------------------------------------------------- import * as os from 'node:os' import * as path from 'node:path' // ============================================================================ /** * Represents a map of substitution values used by Liquid templates. * * @remarks * Values can be strings for simple substitutions or arrays for multi-line * content. Array values are typically joined with newlines when rendered. * * Common use cases: * * * * Templates access these values via namespaces like `properties.foo`, * `matrix.arch`, etc., with the Liquid Drop pattern providing lazy * evaluation and nested substitution support. */ export type LiquidSubstitutionsStrings = Record /** * Defines the substitution variables available to Liquid templates. * * @remarks * This interface mirrors a subset of Node.js environment, operating * system, and path information, along with package-specific configuration * values. * * Variable hierarchy and scoping: * *
    *
  1. Base variables (env, os, * path): Available globally, initialized once * from Node.js runtime at startup.
  2. *
  3. Package variables: Added when processing * package.json, contains * package metadata accessible via package.name, * package.version, * etc.
  4. *
  5. Properties: User-defined values from * xpack.properties, accessible via * properties.key.
  6. *
  7. Configuration: Build configuration metadata, available when * processing configuration-specific templates via * configuration.name, * etc.
  8. *
  9. Matrix: Template expansion parameters, scoped to individual * expanded instances, accessible via matrix.key.
  10. *
* * Variables are inherited and extended through the hierarchy: * * * * This ensures templates have access to appropriate * context without exposing unrelated data. */ export interface LiquidSubstitutionsVariables { /** * Process environment variables from the current execution context. * * @remarks * Provides access to all environment variables via `env.VARIABLE_NAME` * in templates. Common uses include accessing `PATH`, `HOME`, `USER`, or * custom variables set by build scripts. * * See {@link https://nodejs.org/dist/latest-v16.x/docs/api/process.html#process_process_env | Node.js process.env documentation} */ env: NodeJS.ProcessEnv /** * Operating system information from Node.js os module. * * @remarks * Provides platform detection and system information for cross-platform * template logic. Common uses include conditional compilation, path * construction, and platform-specific configuration. * * Key properties for cross-platform templates: * * * * See {@link https://nodejs.org/dist/latest-v16.x/docs/api/os.html | Node.js os module documentation} */ os: { /** * The operating system-specific end-of-line marker. * */ EOL: string /** * Possible values are 'arm', 'arm64', 'ia32', 'mips', 'mipsel', * 'ppc', 'ppc64', 's390', 's390x', 'x32', and 'x64'. */ arch: string /** * Contains commonly used operating system-specific constants * for error codes, process signals, and so on. The specific * constants defined are described in * {@link https://nodejs.org/dist/latest-v16.x/docs/api/os.html#os_os_constants_1 | OS constants} */ constants: { signals: Record errno: Record } /** * An array of objects containing information about * each logical CPU core. */ cpus: os.CpuInfo[] /** * A string identifying the endianness of the CPU * for which the Node.js binary was compiled. * * Possible values are 'BE' for big endian and 'LE' for little endian. */ endianness: 'BE' | 'LE' /** * The string path of the current user's home folder. */ homedir: string /** * The host name of the operating system as a string. */ hostname: string /** * A string identifying the operating system platform. * Possible values are 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', * 'sunos', and 'win32'. */ platform: NodeJS.Platform /** * The operating system as a string. */ release: string /** * Returns the operating system's default folder for * temporary files as a string. */ tmpdir: string /** * Returns the operating system name as returned by uname(3). * For example, it returns 'Linux' on Linux, 'Darwin' on macOS, * and 'Windows_NT' on Windows. */ type: string /** * Returns a string identifying the kernel version. * * On POSIX systems, the operating system release is determined * by calling `uname(3)`. On Windows, `RtlGetVersion()` is used, * and if it is not available, `GetVersionExW()` will be used. */ version: string } /** * Path separators and delimiters from Node.js path module. * * @remarks * Provides platform-specific path constants for building file paths in * templates. Use these to construct paths that work correctly on all * platforms. * * Available constants: * *
    *
  • path.sep: Platform-specific path separator (/ or \).
  • *
  • path.delimiter: Platform-specific PATH delimiter * (; or :).
  • *
  • path.posix.*: Force POSIX conventions regardless of platform.
  • *
  • path.win32.*: Force Windows conventions regardless of platform.
  • *
* * Note: For path manipulation, prefer using Liquid filters like * `path_join`, `path_dirname`, etc., which handle cross-platform concerns * automatically. * * See [Node.js path module documentation](https://nodejs.org/dist/latest-v16.x/docs/api/path.html) */ path: { /** * Provides the platform-specific path delimiter: *
    *
  • ; for Windows
  • *
  • : for POSIX
  • *
*/ delimiter: string /** * Provides the platform-specific path segment separator: *
    *
  • \\ on Windows
  • *
  • / on POSIX
  • *
*/ sep: string win32: { delimiter: string sep: string } posix: { delimiter: string sep: string } } /** * The package metadata exposed to Liquid templates. * * @remarks * Contains the entire `package.json` content, allowing templates to access * package name, version, description, dependencies, and xpack-specific * metadata. * * Common template patterns: * *
    *
  • \{\{ package.name \}\}: Package name for generated * files.
  • *
  • \{\{ package.version \}\}: Version string for * documentation.
  • *
  • \{\{ package.xpack.properties.key \}\}: Access xpack * properties.
  • *
* * Undefined when processing templates outside of a package context. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any package?: any /** * The build configuration exposed to Liquid templates. * * @remarks * Available only when processing templates within a build configuration * context (actions, dependencies, properties belonging to a specific * configuration). * * Contains the configuration name and all configuration properties, * allowing templates to reference the current build context: * *
    *
  • \{\{ configuration.name \}\}: The build configuration * name.
  • *
  • \{\{ configuration.properties.key \}\}: * Configuration-specific * settings.
  • *
* * Undefined when processing package-level templates. */ configuration?: { name: string // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any } /** * The properties map used for substitutions. * * @remarks * User-defined configuration values from `xpack.properties` * in `package.json`. * Provides a namespace for custom template variables without polluting * the global scope. * * Properties support nested substitutions: a property value can reference * other properties, package metadata, or system variables using Liquid * syntax. The Liquid Drop pattern ensures recursive evaluation. * * Access via `{{ properties.key }}` in templates. */ properties: LiquidSubstitutionsStrings /** * Optional matrix parameters used for template expansion. * * @remarks * Available only for actions or configurations generated from templates * with matrix definitions. Each expanded instance receives a specific * combination of matrix values. * * Matrix parameters enable generating multiple similar actions or * configurations from a single template definition. For example, a matrix * with `arch: ['x64', 'arm64']` and `os: ['linux', 'darwin']` generates * 4 instances (x64-linux, x64-darwin, arm64-linux, arm64-darwin). * * Access via `{{ matrix.key }}` in templates. Scoped to the individual * expanded instance, ensuring isolation between generated items. */ matrix?: LiquidSubstitutionsStrings } /** * The base substitution variables initialised from the current environment. * * @remarks * This constant provides the foundation for all Liquid template processing, * capturing the runtime environment once at module load time. * * Initialization strategy: * *
    *
  1. Environment variables: Snapshot of process.env at load time.
  2. *
  3. OS information: OS specific definitions (platform, arch, * etc.).
  4. *
  5. Path constants: Platform-specific separators and delimiters.
  6. *
  7. Properties: Placeholder for package-specific additions.
  8. *
* * These base variables are shared across all template processing within the * application and extended with package, configuration, and matrix variables * as needed. The base object is typically spread into new contexts rather * than mutated, preserving the original snapshot. */ export const liquidSubstitutionsVariablesBase: LiquidSubstitutionsVariables = { env: process.env, os: { EOL: os.EOL, arch: os.arch(), constants: { signals: os.constants.signals, errno: os.constants.errno, }, cpus: os.cpus(), endianness: os.endianness(), homedir: os.homedir(), hostname: os.hostname(), platform: os.platform(), release: os.release(), tmpdir: os.tmpdir(), type: os.type(), // os.version() available since 12.x version: os.version(), }, path: { delimiter: path.delimiter, sep: path.sep, win32: { delimiter: path.win32.delimiter, sep: path.win32.sep, }, posix: { delimiter: path.posix.delimiter, sep: path.posix.sep, }, }, properties: {}, } // ----------------------------------------------------------------------------