87

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]
gnerkus
  • 11,357
  • 6
  • 47
  • 71

11 Answers11

125

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!

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
slacktracer
  • 6,262
  • 6
  • 28
  • 33
  • 5
    This is just about exactly what I was looking for. There are some caveats; some javascript formatting idioms will confuse the repl (I found that `var foo = ""\n\t, bar = "";` didn't work), and certain globals will not be provided (such as `__dirname`, which you can just manually provide at the beginning of your repl session). Otherwise, this is awesome. Very powerful! – T3db0t Jun 30 '13 at 00:41
  • It also fails to work with `someObject.doStuff()\n.doMoreStuff()`. It spits out `Invalid REPL keyword` – seems to be trying to interpret it as some sort of command. – tomekwi Nov 10 '14 at 18:34
  • Glad I kept scrolling +1 – Keon Jun 11 '15 at 03:46
  • Updated this answer so it would be at the top, while clearing up how it worked. – Kyle Kelley Jan 23 '16 at 18:18
  • @KyleKelley Don't do that. http://meta.stackoverflow.com/questions/320291/should-accepted-answers-on-old-questions-be-edited-to-reflect-the-best-answer?cb=1 – cat Apr 02 '16 at 23:20
  • Feel free to fix, I won't do that again. – Kyle Kelley Apr 05 '16 at 15:44
  • I prefer [the solution](https://stackoverflow.com/questions/8425102/how-do-i-load-my-script-into-the-node-js-repl/22817680#22817680) where the file is read in and its contents are fed into `eval` to be preferable since the results don't show up in the history. This should probably only be done using a script that you are completely familiar with. – Dave F Apr 07 '21 at 22:22
32

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.

Laizer
  • 5,932
  • 7
  • 46
  • 73
sarnold
  • 102,305
  • 22
  • 181
  • 238
  • How would I use `vm.runInThisContext()` using repl? –  Dec 19 '11 at 17:34
  • @Matt: heh, I think you're right. I paid more attention to the title _execute some code and then go into interactive node_ than to the question _Is there a way to execute some code ... before dropping into interactive mode in node.js?_, which just sort of _assumes_ that `node` will start an interactive mode. I'm not sure how to answer the different question -- can you add one? Thanks. – sarnold May 15 '12 at 20:44
  • Alas I can't Sarnold, I'm looking for the answer myself! I know the analogous commands `python -i script.py` or `irb -r script.rb` – Colonel Panic May 15 '12 at 21:09
  • 2
    @Matt: I didn't see any way in the `node` source to do what you're asking; you [can write a shell script to do something similar, though](http://css.dzone.com/articles/execute-code-each-time-nodejs). (The `-e` command line switch lets you run commands, but you'd have to write similar code to start a REPL yourself.) – sarnold May 15 '12 at 22:19
  • The first 2 lines work great for me if placed at the bottom of the node script. – Mauvis Ledford Mar 21 '13 at 17:17
  • 1
    [Here](https://gist.github.com/dgmike/381478f5fb60da684f96)'s my version, using repl and a bash script/alias to run it. It works for me... ;-D – dgmike Feb 28 '14 at 14:07
  • 2
    It is very annoying that I have to press Ctrl+q 4 times now to exit... even 2 times was 1 time too many before... how to solve this? – davidhq Feb 28 '16 at 11:16
24

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

gnerkus
  • 11,357
  • 6
  • 47
  • 71
  • 7
    This answer allows to execute some code from input string, but does not allow to _execute the code from a file_ **and** _stay in REPL_. In this way, `node` + .`load ./script.js` answer is better. – jakub.g May 02 '19 at 07:36
  • 1
    In something like bash you can also use `node -i -e "$(< ./script.js)"` for files. – Daniel Sharp Aug 01 '19 at 07:52
  • 3
    `node -i -e "require('./script.js')"` for files too. – user1742529 Mar 26 '20 at 07:19
  • 2
    If you `require('./script.js')`, none of that script's namespace will be available to the interactive sesssion – gastrodon Feb 12 '22 at 19:29
12

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.

Doh Simpson
  • 336
  • 3
  • 5
7

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.

Daniel
  • 8,212
  • 2
  • 43
  • 36
6

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".)

fiddlemath
  • 101
  • 1
  • 7
  • 1
    This did not work for me. The script just executes and goes back to shell. – Mauvis Ledford Mar 21 '13 at 17:13
  • Make sure you include that `-` to cat. It certainly works but you lose the ability to tab complete in the REPL. – Kyle Kelley Jan 23 '16 at 18:17
  • For some reasons (?) using cat to print the `javascript` and passing to node with `-i` options will prevent to use history commands (arrow keys), while these will work using `$node; and the `.load myfile.js`. Of course with the latter you loose a way to make it as a command. – loretoparisi Apr 12 '16 at 13:10
3

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.

Felix Rabe
  • 4,206
  • 4
  • 25
  • 34
2

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.

dthree
  • 19,847
  • 14
  • 77
  • 106
  • How to require specific modules when inside `vorpal`? – loretoparisi Apr 12 '16 at 13:06
  • You can either just require them using vanilla js `require` on startup, or make a Vorpal Command that would require them. Check out the Vorpal API for more details. – dthree Apr 12 '16 at 21:56
0

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

Evan
  • 3,191
  • 4
  • 29
  • 25
  • agree, i'm playing with repl. This is of course a dev tool and I would not recommend it (in any way) for a production environment. plus one of the dependencies is an "include" tool for node... its really all about sharing context to play with stuff that otherwise would be locked inside module encapsulation – neu-rah Nov 13 '15 at 22:29
0

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
neu-rah
  • 1,662
  • 19
  • 32
0

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...

Brian Burns
  • 20,575
  • 8
  • 83
  • 77