All files / apps/cli Cli.ts

100% Statements 67/67
88.88% Branches 8/9
100% Functions 3/3
100% Lines 67/67

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  1x 1x 1x 1x   1x       1x 1x 1x   1x   2x 2x 2x 2x   2x 2x 1x   3x 3x 3x   3x 3x 3x 3x             3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 2x 2x 2x 2x   2x 3x   3x 1x   3x 3x 3x 3x   3x 3x   1x 1x   1x 1x 1x  
#!/usr/bin/env node
import 'reflect-metadata';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Command } from 'commander';
import type { Container } from 'inversify';
import { DispatchActionCommand } from '../../envilder/application/dispatch/DispatchActionCommand.js';
import type { DispatchActionCommandHandler } from '../../envilder/application/dispatch/DispatchActionCommandHandler.js';
import type { CliOptions } from '../../envilder/domain/CliOptions.js';
import type { ILogger } from '../../envilder/domain/ports/ILogger.js';
import { PackageVersionReader } from '../../envilder/infrastructure/package/PackageVersionReader.js';
import { TYPES } from '../../envilder/types.js';
import { Startup } from './Startup.js';
 
let serviceProvider: Container;
 
async function executeCommand(options: CliOptions): Promise<void> {
  const commandHandler = serviceProvider.get<DispatchActionCommandHandler>(
    TYPES.DispatchActionCommandHandler,
  );
 
  const command = DispatchActionCommand.fromCliOptions(options);
  await commandHandler.handleCommand(command);
}
 
export async function main() {
  const program = new Command();
  const version = await readPackageVersion();
 
  program
    .name('envilder')
    .description(
      '🌟 A CLI tool to manage environment variables with AWS SSM. What do you want to do today?\n\n' +
        '✨ Generate a .env file?\n' +
        '  Example: envilder --map=param-map.json --envfile=.env\n\n' +
        '🔄 Sync your local .env file back to AWS SSM?\n' +
        '  Example: envilder --push --map=param-map.json --envfile=.env\n\n' +
        '🎯 Create or update a single secret?\n' +
        '  Example: envilder --push --key=API_KEY --value=secret123 --ssm-path=/my/path\n',
    )
    .version(version)
    .option(
      '--map <path>',
      'Path to the JSON file with environment variable mapping (required for most commands)',
    )
    .option(
      '--envfile <path>',
      'Path to the .env file to be generated or imported (required for most commands)',
    )
    .option('--profile <name>', 'AWS CLI profile to use (optional)')
    .option('--push', 'Push local .env file back to AWS SSM')
    .option(
      '--key <name>',
      'Single environment variable name to push (only with --push)',
    )
    .option(
      '--value <value>',
      'Value of the single environment variable to push (only with --push)',
    )
    .option(
      '--ssm-path <path>',
      'SSM path for the single environment variable (only with --push)',
    )
    .action(async (options: CliOptions) => {
      serviceProvider = Startup.build()
        .configureServices()
        .configureInfrastructure(options.profile)
        .create();
 
      await executeCommand(options);
    });
 
  await program.parseAsync(process.argv);
}
 
function readPackageVersion(): Promise<string> {
  const __filename = fileURLToPath(import.meta.url);
  const __dirname = dirname(__filename);
  const packageJsonPath = join(__dirname, '../../../package.json');
 
  return new PackageVersionReader().getVersion(packageJsonPath);
}
 
main().catch((error) => {
  const logger = serviceProvider.get<ILogger>(TYPES.ILogger);
 
  logger.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
  logger.error(error instanceof Error ? error.message : String(error));
});