Why same wildcards behave differently in shell and npm script? - javascript

I want use ./src/**/*.js to match every js file in ./src folder,no matter how deep the file path is.
so I run ls ./src/**/*.js in the shell and the wildcards behave as I expected, js files like ./src/path1/a.js ./src/path1/path2/b.js and both matched.
And then I add npm script in package.json
{
scripts: {
"test": "ls ./src/**/*.js"
}
}
run npm run test. But now only files like ./src/pah1/a.js are matched.
I don't know why same wildcards behave differently.Can anyone tell me what is the right wildcards that I can use to match every js files in one folder.
Thank you.

They're just different. Shells don't expand **. Try find ./src -name '*.js', instead.

Related

How can I select all folders and subfolders any layers deep with custom file ending?

I made a React app using Create-React-App. I have a testing script in my React app's package.json like this:
"test": "node -r #babel/register -r #babel/polyfill **/*.test.js | tap-color",
This catches and executes the files in src/ like src/App.test.js, but not header.test.js in src/layout/header/header.test.js. And what if I add even more layers of folders? Is there a regex that will catch all folders in src/ and their subfolders no matter how nested with a file ending of .test.js?
Edit: I found this question on StackOverflow. According to that answer you would have to write:
"test": "node -r #babel/register -r #babel/polyfill 'src/**/*.test.js' | tap-color",
which unfortunately matches nothing for me. I'm on Mac.
The question you refer to is not especially useful for your case. My answer there works because Mocha has been designed to pass the patterns you give to it to the glob library for interpretation. So when you do mocha 'src/app/**/*.tests.js' the quotes prevent the shell from interpreting the pattern, Mocha gets src/app/**/*.tests.js as the first pattern given to it, which it gives to glob to get a list of files to actually run. Your case is different at least one crucial way: glob is not involved so there is nothing that can correctly interpret **.
Your first attempt is consistent with what happens when you are using a shell that does not understand **. It is interpreted exactly the same as *. So the shell interprets **/*.test.js as */*.test.js, expands this pattern and passes the result to node.
In your second attempt, you quote the pattern but that does not help you because node does not do pattern interpretation. It tries to load a file at path src/**/*.test.js, interpreted literally. This is not what you want.
I'm not sure what the compatibility implication with Windows are, but you could replace 'src/**/*.test.js' with $(find src -type f -name '*.test.js'). (See the man page for details.) At run-time, the shell will replace this with the result of the find command.
Or for greater simplicity, and less risk of platform issues creeping up, you could use babel-tap like this:
babel-tap 'src/**/*.test.js' | tap-color
If you use babel-tap, there's actually no need for using find because internally babel-tap calls on facilities that use the glob library to interpret the file names passed to it.
I've focused on the file pattern issue but I'm not seeing how what you're trying to do would work, even without the pattern issue. Consider this command, and assume that the files exist:
node -r #babel/register -r #babel/polyfill src/a.test.js src/b.test.js
This is not telling Node to run src/a.test.js and src/b.test.js. Rather, it tells node "run the script src/a.test.js and pass to it the parameter src/b.test.js". I've not used tap very much but I don't recall it working this way. Using babel-tap like I show above also avoids the problem here.

uglifyjs-folder remove console.log & alert from minified files

I am minifying multiple files in a folder using uglifyjs-folder in npm package.json like :
"uglifyjs": "uglifyjs-folder js -eyo build/js"
It is working as intended & minify all files in folder.
I want to remove any console.log & alert while minify but not able to find any option with uglifyjs-folderhttps://www.npmjs.com/package/uglifyjs-folder
Please help.
Short Answer
Unfortunately, uglifyjs-folder does not provide an option to silence the logs.
Solution
You could consider writing a nodejs utility script which utilizes shelljs to:
Invoke the uglifyjs-folder command via the shelljs exec() method.
Prevent logging to console by utilizing the exec() methods silent option.
The following steps further explain how this can be achieved:
Install
Firstly, cd to your project directory and install/add shelljs by running:
npm i -D shelljs
node script
Create a nodejs utility script as follows. Lets name the file: run-uglifyjs-silently.js.
var path = require('path');
var shell = require('shelljs');
var uglifyjsPath = path.normalize('./node_modules/.bin/uglifyjs-folder');
shell.exec(uglifyjsPath + ' js -eyo build/js', { silent: true });
Note: We execute uglifyjs-folder directly from the local ./node_modules/.bin/ directory and utilize path.normalize() for cross-platform purposes.
package.json
Configure the uglifyjs script inside package.json as follows:
{
...
"scripts": {
"uglifyjs": "node run-uglifyjs-silently"
...
},
...
}
Running
Run the script as per normal via the command line. For example:
npm run uglifyjs
Or, for less logging to the console, add the npm run --silent or shorthand equivalent -s option/flag. For example:
npm run uglifyjs -s
Notes:
The example gist above assumes that run-uglifyjs-silently.js is saved at the top-level of your project directory, (i.e. Where package.json resides).
Tip: You could always store run-uglifyjs-silently.js in a hidden directory named .scripts at the top level of your project directory. In which case you'll need to redefine your script in package.json as follows:
{
...
"scripts": {
"uglifyjs": "node .scripts/run-uglifyjs-silently"
...
},
...
}
uglify-folder (in 2021, now?) supports passing in terser configs like so:
$ uglify-folder --config-file uglifyjs.config.json ...other options...
and with uglifyjs.config.json:
{
"compress": {
"drop_console": true
}
}
And all options available here from the API reference.

How to pass browserify --require file to angular module?

I have engineered a build for an Angular SPA using NPM to call the browserify script to bundle it, i.e. you can run from the terminal npm run build:js which calls the following script in package.json:
"build:js": "browserify -r ./params-dev.js -e src/app/index.js -o build/index.js"
What I'm trying to do now is to create two different config objects for prod and QA. Each one will require a different file: params-dev.js or params-prod.js (like in the command above).
I am wondering how to access these variables in the resulting bundle? They are environment specific and some of it points to analytics codes, etc. Furthermore, I'm trying to move them out of the global scope, where they currently live.
Here is a sample of the params files I'd like to include with the bundles. There will be one for prod and one for QA:
var merge = require('merge'),
params = require('./params')
exports.config = merge(params, {
env: 'prod',
analyticsCode: 'blah08yweblah2e823lnblah',
otherProps: '...etc...'
})
So how do I access these variables now in my AngularJS module? I feel like I'm missing something obvious here.
Anyone have any ideas? Please let me know if you need more info.
In case it helps, my index.js looks like
(function () {
// common app require statements
require('blah')
require('blah-2')
angular.module('app', [require('angular-route')])
// etc etc
})()
I figured it out. :) If I add the target to the end of the required file path in the command like so:
"build:js": "browserify -r ./params-dev.js:params -e src/app/index.js -o build/index.js"
I can access the object by adding var params = require('params') to my angular file.

Babelify the files in place, in multiple directories

How can I use babel to transpile the JavaScript files containing ES6 stuff, in different directories? I want the result to be in the same directories (e.g. having foo/bar/index.js, I want to get the ES5 code in the same file, by overriding it).
To override one directory I use:
babel lib/ -d lib
This works for one folder (overrides all the content in the lib directory).
How can I do the same for two or more directories? For example, how can I do that for lib/ and bin/?
AFAIK the babel CLI isn't complex enough to support this use-case in a single command. However you could concatenate two commands to achieve the same result:
babel lib/ -d lib && babel bin/ -d bin
Or you could write a script that does this for you, using gulp or another build tool of your choice. For example (untested):
gulp.task('default', () =>
gulp.src(['bin/**/*.js', 'lib/**/*.js'], { base: './' })
.pipe(babel())
.pipe(gulp.dest('.'))
)
The codemod CLI is perfect for this.
It will just modify your files in place:
codemod --plugin babel-transformer.js src/**/*.js

NPM script needs exact file name

Normally when pointing node to a folder, if there is an index.js file there, we don't need to specify it.
I installed an NPM dependency that I am working on, npm install --save-dev suman.
Suman has an index.js file at the root of its NPM project.
In my NPM scripts for a project that depends on suman, I have this:
"scripts": {
"test": "node node_modules/suman/index.js --rnr test"
}
The above works!
But this doesn't work:
"scripts": {
"test": "node node_modules/suman --rnr test"
}
Why is this?
Perhaps the answer is obvious - the require function in node is capable of such behavior, but node itself is not.
Since the library has a bin in its package.json, you don't need to explicitly provide the path to it. Just run node suman --rnr test and npm will take care of using the correct file.
When you install a dependency with a binary in your node project, npm creates a symlink to that file in ./node_modules/.bin and uses those when running npm scripts.
You need to add the correct path:
"scripts": {
"test": "node ./node_modules/suman --rnr test"
}
Notice the ./
Update:
After thinking about this a bit more, It may not be this easy. But take a look at this link: https://docs.npmjs.com/misc/scripts - #elssar seems to be on the right track.
Sorry that I can't include my thoughts simply as a comment rather than as an answer but I don't yet have enough reputation points to comment. However, perhaps the following is relevant:
If, in your problem, the node command finds the appropriate index.js the same way as is shown in the node documentation for modules, then the documented look-up routine will find a different index.js before finding the one that (I think) you want. Specifically, before trying node_modules/suman/index.js (which is the one you want), node will look to see if the "main" field in node_modules/suman/package.json exists. In suman, it does, and it references lib/index.js (i.e. node_modules/suman/lib/index.js) which is different than the one you want. Is that relevant?
UPDATE: Just to clarify my answer with more generic language...
Your original question is a valid one because, in the absence of any other complications, if dir/index.js exists, then both of the following
node dir/index.js ...
node dir ...
should refer to the same (default) file, i.e. dir/index.js. Thus it is reasonable to be confused when those two commands give different results. The explanation is that there IS a complication: the dir/package.json file effectively redirects node dir ... to use a non-default file. This is because the "main" property refers to dir/some/other/file.js. The rules of precedence specify that, if only a directory name is used, this other file will be used before the default. Thus, you are forced to continue to use the longer and more explicit "working" command from your question.

Categories