cross platform "rm" command - node.js

I currently have the following script in my package.json for deleting all ".js" files in my bundles folder for when I run "npm run build". It works fine when running it in dev servers but breaks when it is run in a Windows machine.
{
"scripts": {
"build": "rm bundles/*.js && webpack",
},
}
Since I am hashing all my build files, I am required to delete them all before adding new ones, such that I don't end up with a bunch of old builds.
Is there a "rm bundles/*.js" that would work in both Mac and Windows?

The npm package rimraf is available for command-line usage in scripts.
First install locally into your project:
$ npm install --save-dev rimraf
Then update the build script in your package.json file:
"scripts": {
"prebuild": "rimraf bundles/*.js",
"build": "webpack"
}
The rimraf command (named after rm -rf) deletes the files.
Documentation:
https://www.npmjs.com/package/rimraf#cli
rimraf is a well established project with over 3,000 4,000 5,000 ⭐s on GitHub.

Take a look at shelljs:
ShellJS is a portable (Windows/Linux/OS X) implementation of Unix
shell commands on top of the Node.js API. You can use it to eliminate
your shell script's dependency on Unix while still keeping its
familiar and powerful commands. You can also install it globally so
you can run it from outside Node projects - say goodbye to those
gnarly Bash scripts!
And further to shelljs/shx, which provides the following example:
{
"scripts": {
"clean": "shx rm -rf build dist && shx echo Done"
}
}
An alternative:
You may also want to take a look at Gulp or Grunt, both so called Task Runners. Gulp has gulp-clean and Grunt has grunt-contrib-clean. Both aim to delete folders and/or files.
Let's take Grunt for example:
Add the Grunt CLI with npm i -g grunt-cli to your system
Add the needed packages to your project with npm i --save-dev grunt grunt-contrib-clean
Create a file named gruntfile.js
Add the following lines:
module.exports = (grunt) => {
'use strict';
grunt.initConfig({
clean: ['bundles'],
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.registerTask('default', ['clean']);
};
Update your script "build": "grunt && webpack"

Cross-platform, no dependencies
If you're like me and don't want to add 11 dependencies just to delete a directory, you can use node exit codes to conditionally run scripts:
e.g. Remove the ./dist folder
{
"scripts": {
"clean": "npm run clean:win && npm run clean:lin",
"clean:win": "node -e \"if (process.platform === 'win32') process.exit(1)\" || , if exist dist rmdir /Q /S dist",
"clean:lin": "node -e \"if (process.platform !== 'win32') process.exit(1)\" || rm -rf dist",
}
}
npm run clean

If you do not concern about 'rm/del not found' console.log, here is the short and simple solution, no additional dependencies are required, rm works on Mac and Linux, del works on Windows:
{
"scripts": {
"build": "(rm bundles/*.js || del bundles/*.js) && webpack",
},
}

Update: recursive-fs added a CLI for deleting a folder so you can now do:
"scripts": {
"clean": "recursive-delete \"./bundles\""
}
Original:
If you decide you don't need 11 additional packages just to delete a single folder, you can use recursive-fs and a short script:
node -e \"require('recursive-fs').rmdirr(require('path').resolve('bundles'), ()=>{})\"
Alternatively, someone could write an NPM package that does this and has only a single dependency on recursive-fs, which would still put it at 9 packages fewer than rimraf. Another option would be to fork recursive-fs and publish an NPM package that includes a CLI in it that makes using it for recursive deletions easier.

Related

running windows Comman_Prompt command through package.json scripts

I need to run in command line (cmd)
npm run build
and after that, I need to run
xcopy C:\fileOne C:\fileTwo
BUT, I would like to run only one command and to execute both of those above.
So I thought maybe my package.json should look like this:
"scripts": {
"build": "react-scripts build",
"copy": "xcopy C:\path\firstFile C:\path\secondFile",
"zack": "npm run build && npm run copy",
},
based on this idea:
"scripts": {
"a1": "command1",
"a2": "command2",
"zack": "npm run a1 && npm run a2",
},
and then I could run in command line:
npm run zack
but I'm not managing to make it happen
(the reason why I'm doing this, is: I want to change source code in SubliteText 3 (HTML JS CSS) and automatically to send (copy-paste) in Eclipse (in some other project) )
I want to do this:
My main problem is how to put local directory path inside the string in package.json file.
Instead of writing commands directly inside the package.json you should write a script file that handles it for you.
Something like
var fs = require('fs');
fs.createReadStream('PATH_TO_FILE_ONE').pipe(fs.createWriteStream('PATH_TO_NEW_FILE'));
save the above script as something like afterBuild.js
and in your package.json just do zack as npm run build && node afterBuild.js
I installed npc module:
npm install ncp -g
npm install ncp --save
then I created a file: afterBuild.js and I inserted this code inside:
var ncp = require("ncp");
ncp("C:/directory/file.txt", "C:/destination/directory/file.txt", callback);
function callback(){} //empty function, I don't need it for the start
and in package.json i wrote:
"scripts": {
"build": "react-scripts build",
"zack": "npm run build && node afterBuild.js"
},
and I run it form command line like:
npm run zack

why package.json script works fine on local project but doesn't work on a dependency project

I have created a npm module(let call it ModuleA) and defined clean script in its package.json file like below:
"scripts": {
"test": "nyc mocha tests/ --opts mocha.opts",
"build": "babel -d dist/ src/",
"prepublish": "yarn run clean && yarn run build",
"postinstall": "yarn run clean && yarn run build",
"clean": "rimraf ./dist"
},
I use rimraf to remove the dist directory. This dependency is defined in devDependencies as "rimraf": "^2.6.1". It works fine on this project. But in one of my other project (let call it ModuleB) which has a dependency on this module, the yarn install doesn't work and I get below error:
$ rimraf ./dist
sh: 1: rimraf: not found
this error happens when npm/yarn is building the ModuleB. I have checked that rimraf exist in node_modules/.bin directory in ModuleB. It works fine if I install rimraf globally. I wonder how I can make the npm/yarn to use rimraf from node_modules/.bin/rimraf?
BTW, I also put the rimraf in devDependencies in ModuleB.
I tried to update the script in ModuleA to use rimraf from node_modules/.bin/rimraf as below:
"clean": "node_modules/.bin/rimraf ./dist"
it works fine on ModuleA. But I got below error when run yarn install on ModuleB:
$ node_modules/.bin/rimraf ./dist
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
sh: node_modules/.bin/rimraf: No such file or directory
error Command failed with exit code 127.
See those issues:
https://github.com/yarnpkg/yarn/issues/721 (postinstall hook doesn't appear to be run #721)
https://github.com/yarnpkg/yarn/issues/853 (preinstall and postinstall are not run #853)
https://github.com/yarnpkg/yarn/issues/614 (Bug: issue with postinstall scripts in git-hooks package)
Now make sure that yarn clean and npm clean works as expected.
For example this will not work if you didn't install rimraf globally:
$ rimraf ./dist
But this should work:
$ ./node_modules/.bin/rimraf ./dist
Test those commands first:
npm run clean
and:
yarn run clean
to use the "clean": "rimraf ./dist" script defined in package.json.
Note that ./node_modules/.bin is added to your PATH when you run package.json scripts.
Try running the commands from the simple ones where you run the script directly without npm or yarn, then test with both npmand yarn, and then finally try to narrow down the problem with postinstall hooks.

Splitting npm scripts into multiple files

is there a way to split npm scripts into multiple files?
Currently I have next structure:
"pages-build-js": "browserify pages/dev/js/init.js -o pages/static/js/bundle.js",
"pages-build-scss": "node-sass pages/dev/scss/init.scss > pages/static/css/main.css",
However, is there a way, I can move these scripts in separate package.json in pages directory and then to run it from parent directory?
The problem is that when I make it, looks like it doesn’t see any local packages from parent directory. How can I solve it?
Thanks
I'm not sure if this is what you want but I had a project where we had a separate package.json for our backend.
To set everything up we hat this in our main package.json
"scripts": {
"setup": "npm install && cd ./src/backend && npm install"
},
Which install all packages from the two files.
You should also be able to run other npm scripts that way
So something like this
"scripts": {
"build-js": "cd ./pages && npm run pages-build-js"
},

Elastic Beanstalk dependencies not available in npm install?

I have read EB Documentation to understand how i can set external dependencies for my app. My app is to be installed in a nodejs container which automatically executes npm install and npm start. So to build the static dependencies I use
"scripts": {
"postinstall": "bower install -F && gulp build",
"start": "node server.js",
"test": "NODE_ENV=test mocha server/test --recursive"
}
Which isnt working fine due to error in gulp build, which is as follows
[12:03:22] Starting 'styles'...
{ [Error: spawn ENOENT: Missing the Sass executable. Please install and make available on your PATH.]
message: 'spawn ENOENT: Missing the Sass executable. Please install and make available on your PATH.',
showStack: false,
showProperties: true,
plugin: 'gulp-ruby-sass',
__safety: { toString: [Function] } }
[12:03:22] 'css' all files 0 B
So I did this
packages:
rubygems:
sass: ''
and placed the file in .ebextensions/01config.config but no change in error. Have tried doing numerous other things but ended up doing the following as my last idea
"postinstall": "bower install -F && gulp build && sh postgulp.sh",
and creating a postgulp.sh file in the project root
#!/bin/bash
pwd
ls
if hash sass 2>/dev/null; then
sass --update ./client/css:./public-debug/css --sourcemap=auto;
else
echo >&2 "I require sass but it's not installed. Continuing without sass.";
fi
Still no luck. Even though I have sass in rubygems dependency but its not in the PATH. Why? When are ebextensions scripts executed as opposed to npm install and postinstall? Why is some thing that is installed in ebextensions only available to those scripts and not to npm? Why dosent gulp-ruby-sass pick up sass?
There can be two versions of ruby on the instance - one in /usr/bin and another one in /opt/elasticbeanstalk/lib/ruby.
Since you said SAAS is installed in the latter you need to make sure that the version of ruby on path when running your app is the same.
Most likely node is trying to use system ruby in /usr/bin and hence cannot find the gem.

Run npm from subdirectories on Heroku

I have a project which contains 2 subprojects:
First is the API
Second is the client
And both of these projects have their own dependencies mapped in their own packages.json files, which is placed in each subdir.
So the question is how to run npm install from sub directories on heroku?
I tried putting something like this in the main npm file
"scripts": {
"postinstall": "cd my_subdir; npm install"
}
But it doesn't work, showing can't cd to my_subdir
Utilize npm's --prefix option:
"scripts": {
"postinstall": "npm install --prefix ./my_subdir"
}

Resources