One of the pleasures of frameworks like Rails is being able to interact with models on the command line. Being very new to node.js, I often find myself pasting chunks of app code into the REPL to play with objects. It's dirty.
Is there a magic bullet that more experienced node developers use to get access to their app specific stuff from within the node prompt? Would a solution be to package up the whole app, or parts of the app, into modules to be require()d? I'm still living in one-big-ol'-file land, so pulling everything out is, while inevitable, a little daunting.
Thanks in advance for any helpful hints you can offer!
One-big-ol'-file land is actually a good place to be in for what you want to do. Nodejs can also require it's REPL in the code itself, which will save you copy and pasting.
Here is a simple example from one of my projects. Near the top of your file do something similar to this:
function _cb() {
console.log(arguments)
}
var repl = require("repl");
var context = repl.start("$ ").context;
context.cb = _cb;
Now just add to the context throughout your code. The _cb is a dummy callback to play with function calls that require one (and see what they'll return).
Seems like the REPL API has changed quite a bit, this code works for me:
var replServer = repl.start({
prompt: "node > ",
input: process.stdin,
output: process.stdout,
useGlobal: true
});
replServer.on('exit', function() {
console.log("REPL DONE");
});
You can also take a look at this answer https://stackoverflow.com/a/27536499/1936097. This code will automatically load a REPL if the file is run directly from node AND add all your declared methods and variables to the context automatically.
Related
I am relatively new to node (moving from PHP) and am encountering a problem that took me a while to figure out (meaning it took me a while to figure out what the problem was and now I have no idea how to fix it).
At the top of my node app (server.js), I have some requires. One of this requires my homemade api like this:
const express = require('express');
const app = express();
const v1 = require('./app/v1.js');
The v1 is just a function that returns the output to the api. However, there are many code problems with the v1 api as I have just wrote it and am testing it for the first time.
However, whenever there is a problem with the v1 function, node doesn't print it out and stop the program like it would if the problem were in the main server.js file. In fact (I am using nodemon so I don't have to restart each time), node just continues running like everything is moving perfectly smoothly. I understand why node would want to do this (they want people's app's to not be dependent on the quality of code of the module). However, this is not helpful for me as I have no idea where my problem is in the v1 module.
Does anyone know how to turn on errors/exceptions for modules? Any help appreciated.
Sounds like its doing its job just fine. Are you sure your v1 is returning the right value? or printing out the value that v1 is returning in server.js? because its not going to automatically print out the returned value, you still have to put it in a console.log(v1()); or something similar. without knowing what v1 actually returns, its hard to say what is suppose to be printed.
Hi I am structuring my Node.js project based on this, like so:
Root
product name
index.js: (contains requires for the product and the main export)
productName.js: contains application logic
test
test1.js
test2.js
...
Now I have two questions
What should logically go in index.js? At the moment I have this (would this be a good way to do things and what else might I include in index.js?):
// index.js
var myServer = require('./myServer.js'); // "product name" = "myServer"
module.exports = {
run: myServer.listen
}
Does it matter what I call the object key in module.exports (currently "run")? Why does the server always run when I execute index.js with $ node index.js how does it automatically know to run myServer.listen?
P.S.: I am aware of web structure auto-generation tools, I just wish to understand the logical reason for this suggested structure (the idea of not having any logic in index.js)
As you mentioned this is a Express service, if it is only handling backend of some application or more specifically this is only backend application, I would suggest you change name of your index.js to server.js(Thus explicitly stating that it'll process all service requests).
But if not then even index.js is fine.
Now for
1
What you've put is absolutely fine, apart from this you could require all modules, routes(or controllers whatever you name them) in a way that it serves as entry point to your application. Try not to put any logic in here.
2
Actually the server runs because it executes the script in the file called index.js, the script says myServer.listen, now if you had written console.log("Hello World") and used $ node index.js it would've printed Hello World instead.
Node just expects and executes script that is there in index.js, in your case it is to start the server.
About the logic that why not put anything else in index.js, for me the reasoning I consider good enough is it provides abstraction as it is the entry point I don't want index.js to worry about things like what to do with this data and all. I believe it should provide a base to setup server. Thus following single responsibility to some extent. Also I won't have to touch it ever in projects lifetime unless some major change occurs e.g. I decide to shift from express to something else.
EDIT
Why have a key called run
You seem to have answered it yourself(in comments), you are giving or more proper description would be you're attaching an object to module.exports as it is a object similar to JSON it was supposed to have a key(which could be anything not necessarily run it could've been hii). Now if you don't want to pass a key and export only one thing that is server.listen then you could write same as module.exports = myServer.listen; instead of
module.exports = {
hii: myServer.listen
}
Note that you could export more modules using the way you did. For more details about module.exports refer this or better google about it as this link might expire anytime and does not seem an ideal thing to put on SO.
I want to make sure that in case the code is running in test mode, that it does not (accidentally) access the wrong database. What is the best way to detect if the code is currently running in test mode?
As already mentioned in comment it is bad practice to build your code aware of tests. I even can't find mentioned topic on SO and even outside.
However, I can think of ways to detect the fact of being launched in test.
For me mocha doesn't add itself to global scope, but adds global.it.
So your check may be
var isInTest = typeof global.it === 'function';
I would suggest to be sure you don't false-detect to add check for global.sinon and global.chai which you most likely used in your node.js tests.
Inspecting process.argv is a good approach in my experience.
For instance if I console.log(process.argv) during a test I get the following:
[
'node',
'/usr/local/bin/gulp',
'test',
'--file',
'getSSAI.test.unit.js',
'--bail',
'--watch'
]
From which you can see that gulp is being used. Using yargs makes interpretting this a whole lot easier.
I strongly agree with Kirill and in general that code shouldn't be aware of the fact that it's being tested (in your case perhaps you could pass in your db binding / connection via a constructor?), for things like logging I can see why you might want to detect this.
Easiest option is to just use the detect-mocha [NPM package.
var detectMocha = require('detect-mocha');
if(detectMocha()) {
// doSomethingFancy
}
If you don't want to do that, the relevant code is just
function isMochaRunning(context) {
return ['afterEach','after','beforeEach','before','describe','it'].every(function(functionName){
return context[functionName] instanceof Function;
})
Where context is the current window or global.
I agreed with #Joshua on his answer, he says Inspecting process.argv is a good approach in my experience.
So, I've written a simple detecting mocha code.
const _MOCHA_PATH = new RegExp('(\\\\|/)node_modules\\1mocha\\1bin\\1_mocha$');
var isMochaRunning = process.argv.findIndex(arg => _MOCHA_PATH.test(arg)) > -1;
In a small project with no logging infrastructure, I use
if (process.env.npm_lifecycle_event !== 'test')
console.error(e);
to avoid logging expected errors during testing, as they would interfere with test output.
var express = require('express');
Debugger;
var router = express.Router();
In node debugger, when the control stops at second line, i do this,
debug> repl
Press Ctrl + C to leave debug repl
> express
[Function]
> express.
here, after 'express.', pressing tab for autocomplete doesn't list out Router option but node builtin properties like hasOwnProperty, call, bind... are there.
express.Router
is defined in
`node_modules/express/lib/router/index.js`.
I see, no reason this property may not be part of the express object.
In summary, node debugger autocompletion is not listing all the properties for express object.
This is a side-effect of the fact that express exports a function rather than a standard object. e.g.
module.exports = function(){ ...}
module.exports.Router = Router;
It all comes down to this line in the Node source, which ends up basically saying "if autocompleting a function, treat it like a simple anonymous function", thus it doesn't have any extra properties.
The reason for the roundabout code is because when you run node debug ..., you are actually starting two node processes, with one running your code, and one running the debugger. That means that when you autocomplete, the debugger process must send a message to the process being debugged, asking for information, and then it has to translate that back into something that you can render for autocompletion.
Looking over the node core source, my educated guess would be that this was simply the easiest thing to do. The current architecture of the debugger tries to hide the debugger implementation as much as possible, but that means that the autocompleter doesn't know that it is working on a faked object copy and the debugger doesn't know that we are autocompleting. The downside of this is that it tries to recursively duplicate the whole object before processing the autocomplete, meaning it does a costly recursive operation to then simply discard the result. Unfortunately adding function property recursion makes the autocomplete quite slow from my quick test a minute ago.
Did anyone set up something like this for himself using the existing
node.js REPL? I didn't think of a quick way to do it.
The way I do it today is using emacs and this:
https://github.com/ivan4th/swank-js
This module is composed of:
A SLIME-js addon to emacs which, in combination with js2-mode, lets
you simply issue a C-M-x somewhere in the body of a function def - and
off goes the function's string to the ..
Swank-js server (yes, you could eval from your local-machine
directly to a remote process) written in Node.js - It receives the
string of the function you eval'ed and actually evals it
A whole part that lets you connect to another port on that server
with your BROWSER and then lets you manipulate the DOM on that browser
(which is pretty amazing but not relevant)
My solution uses SLIME-js on the emacs side AND I require('swank-
js') on my app.js file
Now.. I have several issues and questions regarding my solution or
other possible ones:
Q1: Is this overdoing it? Does someone have a secret way to eval stuff
from nano into his live process?
Q2: I had to change the way swank-js is EVALing.. it used some
kind of black magic like this:
var Script = process.binding('evals').Script;
var evalcx = Script.runInContext;
....
this.context = Script.createContext();
for (var i in global) this.context[i] = global[i];
this.context.module = module;
this.context.require = require;
...
r = evalcx("CODECODE", this.context, "repl");
which, as far I understand, just copies the global variables to the
new context, and upon eval, doesn't change the original function
definitions - SOOO.. I am just using plain "eval" and IT
WORKS.
Do you have any comments regarding this?
Q3: In order to re-eval a function, it needs to be a GLOBAL function -
Is it bad practice to have all function definitions as global (clojure-like) ? Do you think there is another way to do this?
Actually, swank.js is getting much better, and it is now much easier to set up swank js with your project using NPM. I'm in the process of writing the documentation right now, but the functionality is there!
Check this out http://nodejs.org/api/vm.html
var util = require('util'),
vm = require('vm'),
sandbox = {
animal: 'cat',
count: 2
};
vm.runInNewContext('count += 1; name = "kitty"', sandbox, 'myfile.vm');
console.log(util.inspect(sandbox));
// { animal: 'cat', count: 3, name: 'kitty' }
Should help you a lot, all of the sandbox things for node uses it :) but you can use it directly :)
You might take a look at jsapp.us, which runs JS in a sandbox, and then exposes that to the world as a quick little test server. Here's the jsapp.us github repo.
Also, stop into #node.js and ask questions for a quicker response :)