How to pass argument to Mongo Script - javascript

I've been using mongo and script files like this:
$ mongo getSimilar.js
I would like to pass an argument to the file:
$ mongo getSimilar.js apples
And then in the script file pick up the argument passed in.
var arg = $1;
print(arg);

Use --eval and use shell scripting to modify the command passed in.
mongo --eval "print('apples');"
Or make global variables (credit to Tad Marshall):
$ cat addthem.js
printjson( param1 + param2 );
$ ./mongo --nodb --quiet --eval "var param1=7, param2=8" addthem.js
15

You can't do that, but you could put them in another script and load that first:
// vars.js
msg = "apples";
and getSimilar.js was:
print(msg);
Then:
$ mongo vars.js getSimilar.js
MongoDB shell version: blah
connecting to: test
loading file: vars.js
loading file: getSimilar.js
apples
Not quite as convenient, though.

Set a shell var:
password='bladiebla'
Create js script:
cat <<EOT > mongo-create-user.js
print('drop user admin');
db.dropUser('admin');
db.createUser({
user: 'admin',
pwd: '${password}',
roles: [ 'readWrite']
});
EOT
Pass script to mongo:
mongo mongo-create-user.js

I used a shell script to pipe a mongo command to mongo. In the mongo command I used an arg I passed to the shell script (i.e. i used $1):
#!/bin/sh
objId=$1
EVAL="db.account.find({\"_id\" : \"$objId\"})"
echo $EVAL | mongo localhost:27718/balance_mgmt --quiet

2022 update:
when using mongosh you can read the execution arguments from process.argv
mongosh script.js param1 param2
// process.argv will be [.... , 'param1', param2']
the tricky bit is that mongosh will try to execute the parameters (e.g. param1 and param2) as additional scripts, but this can be prevented by ending the script using quit(). (TBH, I'm not sure it's by design / intended / documented)

I wrote a small utility to solve the problem for myself. With the mongoexec utility, you would be able to run the command ./getSimilar.js apples by adding the following to the beginning of your script:
#!/usr/bin/mongoexec --quiet
Within the script, you can then access the arguments as args[0].
https://github.com/pveierland/mongoexec

I solved this problem, by using the javascript bundler parcel: https://parceljs.org/
With this, one can use node environment variables in a script like:
var collection = process.env.COLLECTION;
when building with parcel, the env var gets inlined:
parcel build ./src/index.js --no-source-maps
The only downside is, that you have to rebuild the script every time you want to change the env vars. But since parcel is really fast, this is not really a problem imho.

Related

How to get Jenkins BUILD_NUMBER in JavaScript using GULP/NODE?

I have a gulp task getBuildNumber which uses Child Process to execute the script.
gulp.task('getBuildNumber', function() {
var buildNumber = child_process.execSync("echo $BUILD_NUMBER").toString().trim();
console.log(buildNumber);
});
When I run the following command for gulp
npm run gulp -- getBuildNumber
I always get the output as $BUILD_NUMBER and not the actual Jenkins build number.
Can someone please suggest on how to proceed with this?
You can access environment variables with process.env.
For example:
console.log(process.env.BUILD_NUMBER);
According to https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback, you need to escape special characters:
exec('echo "The \\$HOME variable is $HOME"');
In your case, this means you'd need to use
[...]child_process.execSync("echo \\$BUILD_NUMBER").toString().trim();[...]
^^

named parameter to npm run script

I would like to pass a named parameter to an npm run script so I can do something like the following:
"scripts":{
"say-hello":"echo $greeting && ls"
}
npm run hello --greeting=hello
I'd like it to then put 'hello' in place of the $greeting variable, echo the command and then do the ls (this is obviously just a simple example of a chained command)
Just found out that this works:
"scripts":{
"say-hello" : "echo $npm_config_greeting && ls"
}
Edit:
Any environment variables that start with npm_config_ will be interpreted as a configuration parameter. For example, putting npm_config_foo=bar in your environment will set the foo configuration parameter to bar.
npm docs
Another way is to simply add the following '--' followed by your desired param(s). This would be for named parameters that '=' a value. Please note the underlying process in this example, a protractor call, expects a Url arg.
npm run e2e -- --Url="https://yoururlhere.com"

MongoDB: How to call a function defined in another JS file?

I have a function defined called func1 in file file_a.js
I have another file file_b.js, in which I want to use the function func1.
Can I do this inside mongo environment?
Amended answer thanks to AD7six
Mongodb console can take multiple input file loaded in order specified.
Or you can use the built in load function like this
➜ mongotest cat test.js
load("test2.js");
print("test.js");
foo();
➜ mongotest cat test2.js
var foo = function() {
print("test2.js");
};
➜ mongotest mongo test.js
MongoDB shell version: 2.0.6
connecting to: test
test.js
test2.js
test.js is the file given to mongodb console, it loads test2.js(containing function foo) and calls foo
If you are meaning via the cli (are you?), you can load multiple js files via the mongo shell
$ mongo --help
MongoDB shell version: 2.0.6
usage: mongo [options] [db address] [file names (ending in .js)]
Note file name s
Therefore, you can just load both files, and the contents of file_a will be available to file_b:
mongo [args] dbname file_a.js file_b.js

execute some code and then go into interactive node

Is there a way to execute some code (in a file or from a string, doesn't really matter) before dropping into interactive mode in node.js?
For example, if I create a script __preamble__.js which contains:
console.log("preamble executed! poor guy!");
and a user types node __preamble__.js they get this output:
preamble executed! poor guy!
> [interactive mode]
Really old question but...
I was looking for something similar, I believe, and found out this.
You can open the REPL (typing node on your terminal) and then load a file.
Like this: .load ./script.js.
Press enter and the file content will be executed. Now everything created (object, variable, function) in your script will be available.
For example:
// script.js
var y = {
name: 'obj',
status: true
};
var x = setInterval(function () {
console.log('As time goes by...');
}, 5000);
On the REPL:
//REPL
.load ./script.js
Now you type on the REPL and interact with the "living code".
You can console.log(y) or clearInterval(x);
It will be a bit odd, cause "As time goes by..." keep showing up every five seconds (or so).
But it will work!
You can start a new repl in your Node software pretty easily:
var repl = require("repl");
var r = repl.start("node> ");
r.context.pause = pauseHTTP;
r.context.resume = resumeHTTP;
From within the REPL you can then call pause() or resume() and execute the functions pauseHTTP() and resumeHTTP() directly. Just assign whatever you want to expose to the REPL's context member.
This can be achieved with the current version of NodeJS (5.9.1):
$ node -i -e "console.log('A message')"
The -e flag evaluates the string and the -i flag begins the interactive mode.
You can read more in the referenced pull request
node -r allows you to require a module when REPL starts up. NODE_PATH sets the module search path. So you can run something like this on your command line:
NODE_PATH=. node -r myscript.js
This should put you in a REPL with your script loaded.
I've recently started a project to create an advanced interactive shell for Node and associated languages like CoffeeScript. One of the features is loading a file or string in the context of the interpreter at startup which takes into account the loaded language.
http://danielgtaylor.github.com/nesh/
Examples:
# Load a string (Javascript)
nesh -e 'var hello = function (name) { return "Hello, " + name; };'
# Load a string (CoffeeScript)
nesh -c -e 'hello = (name) -> "Hello, #{name}"'
# Load a file (Javascript)
nesh -e hello.js
# Load a file (CoffeeScript)
nesh -c -e hello.coffee
Then in the interpreter you can access the hello function.
Edit: Ignore this. #jaywalking101's answer is much better. Do that instead.
If you're running from inside a Bash shell (Linux, OS X, Cygwin), then
cat __preamble__.js - | node -i
will work. This also spews lots of noise from evaluating each line of preamble.js, but afterwords you land in an interactive shell in the context you want.
(The '-' to 'cat' just specifies "use standard input".)
Similar answer to #slacktracer, but if you are fine using global in your script, you can simply require it instead of (learning and) using .load.
Example lib.js:
global.x = 123;
Example node session:
$ node
> require('./lib')
{}
> x
123
As a nice side-effect, you don't even have to do the var x = require('x'); 0 dance, as module.exports remains an empty object and thus the require result will not fill up your screen with the module's content.
Vorpal.js was built to do just this. It provides an API for building an interactive CLI in the context of your application.
It includes plugins, and one of these is Vorpal-REPL. This lets you type repl and this will drop you into a REPL within the context of your application.
Example to implement:
var vorpal = require('vorpal')();
var repl = require('vorpal-repl');
vorpal.use(repl).show();
// Now you do your custom code...
// If you want to automatically jump
// into REPl mode, just do this:
vorpal.exec('repl');
That's all!
Disclaimer: I wrote Vorpal.
There isn't a way do this natively. You can either enter the node interactive shell node or run a script you have node myScrpt.js. #sarnold is right, in that if you want that for your app, you will need to make it yourself, and using the repl toolkit is helpful for that kind of thing
nit-tool lets you load a node module into the repl interactive and have access to inner module environment (join context) for development purposes
npm install nit-tool -g
First I tried
$ node --interactive foo.js
but it just runs foo.js, with no REPL.
If you're using export and import in your js, run npm init -y, then tell node that you're using modules with the "type": "module", line -
{
"name": "neomem",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "home.js",
"keywords": [],
"author": "",
"license": "ISC"
}
Then you can run node and import a file with dynamic import -
$ node
Welcome to Node.js v18.1.0.
Type ".help" for more information.
> home = await import('./home.js')
[Module: null prototype] {
get: [AsyncFunction: get],
start: [AsyncFunction: start]
}
> home.get('hello')
Kind of a roundabout way of doing it - having a command line switch would be nice...

How do I load my script into the node.js REPL?

I have a script foo.js that contains some functions I want to play with in the REPL.
Is there a way to have node execute my script and then jump into a REPL with all the declared globals, like I can with python -i foo.py or ghci foo.hs?
There is still nothing built-in to provide the exact functionality you describe. However, an alternative to using require it to use the .load command within the REPL, like such:
.load foo.js
It loads the file in line by line just as if you had typed it in the REPL. Unlike require this pollutes the REPL history with the commands you loaded. However, it has the advantage of being repeatable because it is not cached like require.
Which is better for you will depend on your use case.
Edit: It has limited applicability because it does not work in strict mode, but three years later I have learned that if your script does not have 'use strict', you can use eval to load your script without polluting the REPL history:
var fs = require('fs');
eval(fs.readFileSync('foo.js').toString())
i always use this command
node -i -e "$(< yourScript.js)"
works exactly as in Python without any packages.
I made Vorpal.js, which handles this problem by turning your node add into an interactive CLI. It supports a REPL extension, which drops you into a REPL within the context of your running app.
var vorpal = require('vorpal')();
var repl = require('vorpal-repl');
vorpal
.delimiter('myapp>')
.use(repl)
.show()
.parse(process.argv);
Then you can run the app and it will drop into a REPL.
$ node myapp.js repl
myapp> repl:
Another way is to define those functions as global.
global.helloWorld = function() { console.log("Hello World"); }
Then preload the file in the REPL as:
node -r ./file.js
Then the function helloWorld can be accessed directly in the REPL.
Here's a bash function version of
George's answer:
noderepl() {
FILE_CONTENTS="$(< $1 )"
node -i -e "$FILE_CONTENTS"
}
If you put this in your ~/.bash_profile you can use it like an alias, i.e.:
noderepl foo.js
I created replpad since I got tired of reloading the script repeatedly.
Simply install it via: npm install -g replpad
Then use it by running: replpad
If you want it to watch all files in the current and all subdirectories and pipe them into the repl when they change do: replpad .
Check out the videos on the site to get a better idea of how it works and learn about some other nice features that it has like these:
access core module docs in the repl via the dox() function that is added to every core function, i.e. fs.readdir.dox()
access user module readmes in the repl via the dox() function that is added to every module installed via npm,
i.e. marked.dox()
access function's highlighted source code, info on where function was defined (file, linenumber) and function
comments and/or jsdocs where possible via the src property that is added to every function, i.e. express.logger.src
scriptie-talkie support (see .talk command)
adds commands and keyboard shortcuts
vim key bindings
key map support
parens matching via match token plugin
appends code entered in repl back to file via keyboard shortcut or .append command
See: https://github.com/thlorenz/replpad
Why not load the file into an interactive node repl?
node -h
-e, --eval script evaluate script
-i, --interactive always enter the REPL even if stdin
node -e 'var client = require("./build/main/index.js"); console.log("Use `client` in repl")' -i
Then you can add to package.json scripts
"repl": "node -e 'var client = require(\"./build/main/index.js\"); console.log(\"Use `client` in repl\")' -i",
tested using node v8.1.2
Currently you can't do that directly, but you can mylib = require('./foo.js') in the REPL. Remember methods are exported, not declared as globals.
replpad is cool, but for a quick and easy way to load a file into node, import its variables and start a repl, you can add the following code to the end of your .js file
if (require.main === module){
(function() {
var _context = require('repl').start({prompt: '$> '}).context;
var scope = require('lexical-scope')(require('fs').readFileSync(__filename));
for (var name in scope.locals[''] )
_context[scope.locals[''][name]] = eval(scope.locals[''][name]);
for (name in scope.globals.exported)
_context[scope.globals.exported[name]] = eval(scope.globals.exported[name]);
})();
}
Now if your file is src.js, running node src.js will start node, load the file, start a REPL, and copy all the objects declared as var at the top level as well as any exported globals.
The if (require.main === module) ensures that this code will not be executed if src.js is included through a require statement. I fact, you can add any code you want to be excuted when you are running src.js standalone for debugging purposes inside the if statement.
Another suggestion that I do not see here: try this little bit of code
#!/usr/bin/env node
'use strict';
const repl = require('repl');
const cli = repl.start({ replMode: repl.REPL_MODE_STRICT });
cli.context.foo = require('./foo'); // injects it into the repl
Then you can simply run this script and it will include foo as a variable
Old answer
type test.js|node -i
Will open the node REPL and type in all lines from test.js into REPL, but for some reason node will quit after file ends
Another problem is, that functions will not be hoisted.
Better answer
node -e require('repl').start({useGlobal:true}); -r ./test2.js
Then all globals declared without var within test2.js will be available in the REPL
not sure why var a in global scope will not be available
There is an Official Node.js REPL that supports also async methods
console.js
const repl = require('repl')
const mongoose = require('mongoose')
const run = async () => {
await mongoose.connect(process.env.DB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const r = repl.start(`(${process.env.NODE_EN}) ⚡️ `)
r.context.User = require('./src/models/user.model')
r.context.mongoose = mongoose
console.log(`Ready 🚀`);
}
run()
Start the console:
NODE_OPTIONS=--experimental-repl-await node console.js
User model its exposed to console
await User.find({})
source

Categories

Resources