All files / packages/design-system/scripts/scs config-loader.js

96.66% Statements 29/30
95% Branches 38/40
100% Functions 3/3
96.29% Lines 26/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125                                              10x   10x 1x     9x 9x   9x 32x     32x     18x     15x 15x 15x 15x       9x                                         4x     2x   2x 2x         2x 2x     2x                                                     2x 1x         1x 1x     2x    
/**
 * Configuration Loader for SCS Script
 *
 * Loads configuration from multiple sources with the following priority:
 * 1. CLI arguments (--key=value)
 * 2. Environment variables
 * 3. .release-config (shell-style KEY=VALUE file) for versions, WI, CODE_DIR
 * 4. .distrc.json (nconf JSON file) for nexusCreds, localCorePath
 * 5. Interactive prompts for anything not provided
 */
import fs from 'node:fs';
import path from 'node:path';
import nconf from 'nconf';
 
/**
 * Parse a shell-style .release-config file into a key-value object.
 * Handles lines like: KEY="value" or KEY=value
 * Ignores comments (#) and blank lines.
 *
 * @param {string} filePath - Path to the .release-config file
 * @returns {Object} Parsed key-value pairs
 */
export function parseReleaseConfig(filePath) {
  const config = {};
 
  if (!fs.existsSync(filePath)) {
    return config;
  }
 
  const content = fs.readFileSync(filePath, 'utf8');
  const lines = content.split('\n');
 
  for (const line of lines) {
    const trimmed = line.trim();
 
    // Skip empty lines and comments
    if (!trimmed || trimmed.startsWith('#')) continue;
 
    // Skip shell directives (export, source, set, etc.)
    if (/^(export|source|set|if|fi|else|elif|return|echo)\b/.test(trimmed)) continue;
 
    // Match KEY=VALUE or KEY="VALUE" patterns
    const match = trimmed.match(/^([A-Z_][A-Z0-9_]*)=["']?(.+?)["']?$/);
    Eif (match) {
      const [, key, value] = match;
      config[key] = value;
    }
  }
 
  return config;
}
 
/**
 * Load all configuration sources and return a merged config object.
 *
 * @param {string} packageRoot - Absolute path to packages/design-system
 * @returns {Object} Merged configuration with the following keys:
 *   - sldsVersion: SLDS1 version string
 *   - slds2Version: SLDS2 version string
 *   - scsVersion: SCS version string
 *   - wi: Work Item ID (SCS_WI)
 *   - codeDir: CODE_DIR for locating sibling repos
 *   - nexusCreds: Nexus credentials (user:pass)
 *   - case: GUS Change Case number
 *   - patch: whether to target patch branch
 *   - doPR: whether to create PR
 *   - scsRepoPath: computed path to slds-scs repo
 *   - scsPatchBranch: SCS patch branch name from release config
 */
export function loadConfig(packageRoot) {
  const rootPath = (...args) => path.resolve(packageRoot, ...args);
 
  // Load nconf with CLI args, env vars, and .distrc.json
  nconf.argv().env();
 
  const distrcPath = rootPath('.distrc.json');
  Iif (fs.existsSync(distrcPath)) {
    nconf.file({ file: distrcPath });
  }
 
  // Parse .release-config for version info, WI, and paths
  const releaseConfigPath = rootPath('.release-config');
  const releaseConfig = parseReleaseConfig(releaseConfigPath);
 
  // Build merged config with priority: CLI > env > .release-config > .distrc.json
  const config = {
    // Versions - from CLI, env, or .release-config
    sldsVersion: nconf.get('sldsVersion') || releaseConfig.SLDS1_VERSION || null,
    slds2Version: nconf.get('slds2Version') || releaseConfig.SLDS2_VERSION || null,
    scsVersion: nconf.get('scsVersion') || releaseConfig.SCS_VERSION || null,
 
    // Work item - from CLI, env (SCS_WI), or .release-config
    wi: nconf.get('wi') || process.env.SCS_WI || releaseConfig.SCS_WI || null,
 
    // GUS Change Case - from CLI or .distrc.json
    case: nconf.get('case') || null,
 
    // Nexus credentials - from CLI or .distrc.json
    nexusCreds: nconf.get('nexusCreds') || null,
 
    // PR and patch toggles - from CLI
    doPR: nconf.get('doPR') || null,
    patch: nconf.get('patch') || null,
 
    // CODE_DIR from .release-config for locating sibling repos
    codeDir: nconf.get('codeDir') || releaseConfig.CODE_DIR || null,
 
    // SCS patch branch from .release-config
    scsPatchBranch: releaseConfig.SCS_PATCH_BRANCH || null,
  };
 
  // Compute slds-scs repo path
  if (config.codeDir) {
    config.scsRepoPath = path.resolve(config.codeDir, 'slds-scs');
  } else {
    // Fallback: ../slds-scs relative to the monorepo root
    // packageRoot = .../salesforce-design-system/packages/design-system
    // monorepo root = ../.. from packageRoot
    const monorepoRoot = path.resolve(packageRoot, '../..');
    config.scsRepoPath = path.resolve(monorepoRoot, '../slds-scs');
  }
 
  return config;
}