Skip to content

Improve CLI logging #5

@kasunben

Description

@kasunben
#!/usr/bin/env node

var Command = require('commander').Command;
var simpleGit = require('simple-git');
var path = require('path');
var fs = require('fs-extra');
var spawn = require('child_process').spawn;
var ora = require('ora');

var program = new Command();
var git = simpleGit();

let chalk;
import('chalk').then(module => {
  chalk = module.default;
});

var pkg = require('../package.json');

var templateRepoUrl = 'https://github.com/hydra-js/hello-world.git';

program.name('hydra').description(pkg.description).version(pkg.version);

program
  .command('create [namespace]')
  .description('Initialize a Hydra App')
  .option('-f, --force', 'Force creation even if directory exists')
  .action(function (namespace, options) {
    namespace = namespace || 'my-hydra-app';
    console.log(chalk.blue('Creating a new Hydra app...'));

    // Resolve paths
    var tempRepoPath = path.join(process.cwd(), namespace, '__hydra');
    var appPath = path.join(process.cwd(), namespace);

    if (fs.existsSync(appPath) && !options.force) {
      console.error(
        chalk.red('Error: Directory ' +
          namespace +
          ' already exists. Use --force to overwrite.')
      );
      process.exit(1);
    }

    if (fs.existsSync(appPath) && options.force) {
      console.log(chalk.yellow('Directory ' + namespace + ' already exists. Overwriting...'));
      fs.removeSync(appPath);
    }

    var spinner = ora('Cloning template repository...').start();

    git
      .clone(templateRepoUrl, tempRepoPath)
      .then(function () {
        spinner.succeed('Repository cloned successfully.');

        var sourcePath = tempRepoPath;

        if (!fs.existsSync(sourcePath)) {
          throw new Error(tempRepoPath + ' does not exist in the repository.');
        }

        spinner.text = 'Copying files to ' + namespace + '...';
        spinner.start();
        return fs.copy(sourcePath, appPath);
      })
      .then(function () {
        spinner.succeed('File structure created successfully.');

        /**
         * @TODO: Make necessary changes
         * - Improve logs
         * -- Show progress
         * -- Show next steps
         * - Create .env file
         * - Install dependencies
        */

        spinner.text = 'Cleaning up temporary files...';
        spinner.start();
        return fs.remove(tempRepoPath);
      })
      .then(function () {
        spinner.succeed('Cleanup completed.');
        console.log(chalk.green('Project ' + namespace + ' generated successfully.'));
        console.log(chalk.cyan('\nNext steps:'));
        console.log(chalk.cyan('1. cd ' + namespace));
        console.log(chalk.cyan('2. npm install'));
        console.log(chalk.cyan('3. npm run dev'));
      })
      .catch(function (err) {
        spinner.fail('Failed to generate project: ' + err.message);
        fs.remove(tempRepoPath);
        process.exit(1);
      });
  });

program
  .command('serve')
  .description('Start the Hydra server')
  .option('-s, --script <script>', 'Specify the npm script to run', 'start')
  .option('-d, --dev', 'Run in development mode')
  .action(function (options) {
    var spinner = ora('Checking application integrity...').start();

    // Validate if the current directory is a Hydra app
    if (!fs.existsSync('package.json')) {
      spinner.fail('package.json not found. Are you in the Application root?');
      process.exit(1);
    }

    // Read package.json to check for necessary scripts and dependencies
    var packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));

    // Determine which script to run
    var scriptToRun = options.dev ? 'dev' : options.script;

    // Check if the specified script exists
    if (!packageJson.scripts || !packageJson.scripts[scriptToRun]) {
      spinner.fail('Script \'' + scriptToRun + '\' not found in package.json');
      process.exit(1);
    }

    // Check for essential dependencies
    var requiredDeps = ['@hydra-js/core'];
    var missingDeps = requiredDeps.filter(function(dep) {
      return !packageJson.dependencies || !packageJson.dependencies[dep];
    });

    if (missingDeps.length > 0) {
      spinner.fail('Missing essential dependencies: ' + missingDeps.join(', '));
      process.exit(1);
    }

    spinner.succeed('Application integrity check passed.');
    console.log(chalk.blue('Running npm script: ' + scriptToRun));

    var npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
    var child = spawn(npm, ['run', scriptToRun], { stdio: 'inherit' });

    child.on('close', function(code) {
      console.log(chalk.yellow('npm script exited with code ' + code));
    });

    child.on('error', function(err) {
      console.error(chalk.red('Failed to start npm script:', err));
      process.exit(1);
    });
  });

program.parse(process.argv);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions