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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions