celsomtrindade
celsomtrindade

Reputation: 4671

How to pass arguments from command line to npm and grunt?

I'm trying to automate some process on my workflow and in order to do that, I need to use some variables to control the environment I'm working on.

I'll start with a simple example I'm trying to do which is a command to create a new folder and copy some boilerplate files. To do it I'm using npm and grunt, like this:

package.json

"scripts": {
  "new": "grunt new --target
},

grunt.js

module.exports = function (grunt) {
  const target = grunt.option('target');
  console.log('Target: ', target);

  grunt.config.set('copy', {
    new: {
      files: [{
        expand: true,
        cwd: 'assets/zip',
        src: '*.zip',
        dest: 'projects/',
      }]
    },
  });
}

And I'm trying to call this like this:

npm run new --target:my-folder-name

This is just a simple example, I'm running other scripts such as unzip files, rename, copy, process scss, etc...

What I expect is the task to run a copy the files to a folder called my-folder-name but it's not happening. The console is printing true, not the folder name.

What do I need to do to pass the argument to the script?

Upvotes: 1

Views: 642

Answers (1)

RobC
RobC

Reputation: 24952

Let's say our contrived project directory is structured as follows:

.
├── Gruntfile.js
├── assets
│   └── zip
│       ├── file1.zip
│       ├── file2.zip
│       └── file3.zip
├── node_modules
│   └── ...
└── package.json

Then consider the following Gruntfile.js example that utilizes grunt-contrib-copy:

Gruntfile.js

module.exports = function(grunt) {

  const target = grunt.option('target') || 'foobar'; // default dir is `foobar`.

  grunt.loadNpmTasks('grunt-contrib-copy');


  grunt.initConfig({
    copy: {
      zips: {
        files: [{
          expand: true,
          cwd: 'assets/zip',
          src: '*.zip',
          dest: 'projects/' + target
        }]
      }
    }
  });

  grunt.registerTask('copy-zips', [ 'copy:zips' ]);

};

The output via the grunt command.

  1. If we cd to the project directory and run the following grunt command:

    grunt copy-zips
    

    the following folders (projects/foobar) are created in the root of the project directory.

    Results Example A

    .
    ├── ...
    └── projects
        └── foobar
            ├── file1.zip
            ├── file2.zip
            └── file3.zip
    

    Note the default foobar folder has been created containing a copy of the *.zip files. The folder was named foobar because we DID NOT provide an argument via the command line.

  2. Next, If we cd to the project directory again and run the following grunt command:

    grunt copy-zips --target=my-folder-name
    

    the following folders (projects/my-folder-name) are created in the root of the project directory.

    Results Example B

    .
    ├── ...
    └── projects
        └── my-folder-name
            ├── file1.zip
            ├── file2.zip
            └── file3.zip
    

    Note This time the my-folder-name folder has been created containing a copy of the *.zip files because we provided the --target=my-folder-name argument/option.

The output via the npm command.

Firstly let's configure the scripts section in the projects package.json as follows:

package,json

{
  ...
  "scripts": {
    "copy-zips": "grunt copy-zips"
  },
  ...
}

  1. If we cd to the project directory and run the following npm command:

    npm run copy-zips
    

    we yield the same results as shown in the aforementioned Results Example A section.

  2. Next, If we cd to the project directory again and run the following npm command:

    npm run copy-zips -- --target=my-folder-name
    

    we yield the same results as shown in the aforementioned Results Example B section.

    Note: The additional -- option between npm run copy-zips and the argument --target=my-folder-name.

    The npm docs describe the -- option as follows:

    As of [email protected], you can use custom arguments when executing scripts. The special option -- is used by getopt to delimit the end of the options. npm will pass all the arguments after the -- directly to your script:


Additional note:

If you don't want to create the my-folder-name folder inside the projects folder, and instead you want to create the my-folder-name folder in the root of the project directory, then you can redefine the dest property in the copy task as follows:

Gruntfile.js

  // ...

  grunt.initConfig({
    copy: {
      zips: {
        files: [{
          expand: true,
          cwd: 'assets/zip',
          src: '*.zip',
          dest: target // <-----
        }]
      }
    }
  });

  // ...

Running the same command:

npm run copy-zips -- --target=my-folder-name

yields the following result:

.
├── ...
└── my-folder-name
    ├── file1.zip
    ├── file2.zip
    └── file3.zip  

Upvotes: 2

Related Questions