All files / src/cli/application EnvilderHandler.ts

100% Statements 64/64
88.23% Branches 15/17
100% Functions 4/4
100% Lines 64/64

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      1x       1x 7x 7x 7x                   1x 7x 7x 6x 6x   6x   5x   5x 7x 2x 2x 2x 2x 2x 7x   1x 6x 6x 6x 6x 6x 9x 9x 9x 9x 9x 9x 1x 1x 9x 6x 1x 1x 1x 1x 5x 6x   1x 9x 9x 9x 9x 9x 9x 9x 1x 1x 1x 7x 7x 9x 9x 9x 9x 1x 1x 1x 9x 1x  
import type { IEnvFileManager } from '../domain/ports/IEnvFileManager';
import type { ISecretProvider } from '../domain/ports/ISecretProvider';
 
export class Envilder {
  private keyVault: ISecretProvider;
  private envFileManager: IEnvFileManager;
 
  constructor(keyVault: ISecretProvider, envFileManager: IEnvFileManager) {
    this.keyVault = keyVault;
    this.envFileManager = envFileManager;
  }
 
  /**
   * Orchestrates the process of fetching environment variable values from a key vault and writing them to a local environment file.
   *
   * Loads a parameter mapping from a JSON file, retrieves existing environment variables, fetches updated values from the key vault, merges them, and writes the result to the specified environment file.
   *
   * @param mapPath - Path to the JSON file mapping environment variable names to key vault parameter names.
   * @param envFilePath - Path to the local environment file to read and update.
   */
  async run(mapPath: string, envFilePath: string) {
    try {
      const requestVariables = await this.envFileManager.loadMapFile(mapPath);
      const currentVariables =
        await this.envFileManager.loadEnvFile(envFilePath);
 
      const envilded = await this.envild(requestVariables, currentVariables);
 
      await this.envFileManager.saveEnvFile(envFilePath, envilded);
 
      console.log(`Environment File generated at '${envFilePath}'`);
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      console.error(`Failed to generate environment file: ${errorMessage}`);
      throw error;
    }
  }
 
  private async envild(
    paramMap: Record<string, string>,
    existingEnvVariables: Record<string, string>,
  ): Promise<Record<string, string>> {
    const errors: string[] = [];
    for (const [envVar, secretName] of Object.entries(paramMap)) {
      const error = await this.processSecret(
        envVar,
        secretName,
        existingEnvVariables,
      );
      if (error) {
        errors.push(error);
      }
    }
    if (errors.length > 0) {
      throw new Error(
        `Some parameters could not be fetched:\n${errors.join('\n')}`,
      );
    }
    return existingEnvVariables;
  }
 
  private async processSecret(
    envVar: string,
    secretName: string,
    existingEnvVariables: Record<string, string>,
  ): Promise<string | null> {
    try {
      const value = await this.keyVault.getSecret(secretName);
      if (!value) {
        console.error(`Warning: No value found for: '${secretName}'`);
        return null;
      }
      existingEnvVariables[envVar] = value;
      console.log(
        `${envVar}=${value.length > 10 ? '*'.repeat(value.length - 3) + value.slice(-3) : '*'.repeat(value.length)}`,
      );
      return null;
    } catch (error) {
      console.error(`Error fetching parameter: '${secretName}'`);
      return `ParameterNotFound: ${secretName}`;
    }
  }
}