Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can node.js execute JavaScript functions pulled from CouchDB like CouchApp does? How?

The quick overview is this: for my web app I can write most of my functionality using CouchApp and CouchDB views, etc. I love the feature of CouchApp that pushes my code up to the server via replication- this makes the deployment cycle very easy.

However, to do some arbitrary work not supported in couchdb and works around a few limitations, I need to put a web platform in front of CouchDB. I'm considering building this in node.js because it uses JavaScript and I want to continue the easy deployment method of pushing code into the database.

Here's how i imagine it working: - I write a web server/service in node.js using the normal method and the node command to start it. - this sevice connects to couch db and gets a virtual list and a URL mapping list. This list is stored in redis for quick lookup. This list will tell the server, when it gets a request, based on host and path, etc, which handler is to be run. - the server fetches the handler- which is just a document, it could be a design document or an arbitrary json document in couchdb. And then executes that handler to handle the request, as if I'd writte the handler as part of node js.

So the question is, how to get a son data structure that contains a JavaScript function in it, in text form, and execute that function?

This may be blindingly obvious, but i come from a compiled background, so normally there would be a compilation step here that makes this pretty much impossible.

So, what I'm thinking is in pseudo code: Var string thecode = getValueForMapKey(handlerFunctionIWant); somehowmagicallyexecute(thecode)

Is there an exec or run function that will do the magical execution step above in JavaScript?

like image 683
Jim Avatar asked Dec 21 '22 23:12

Jim


1 Answers

It will run in the node.js context.

You can also use it in node, like this, as a dynamic function:

var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');

db.get('_design/node%2Fyour_code', function (err, doc) {
  if (!err){
    var your_code = new Function(doc['arguments'].join(','), doc.code);
    your_code("cool", "also cool");
  }else{
    console.error('error:', err);
  }
});

make your docs look like this:

{
   "_id": "_design/node/your_code",
   "arguments": [
       "nameOfArg1",
       "nameOfArg2"
   ],
   "code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
}

It's in the same scope as where the new Function is called, so you have access to cradle, or you can require other libs, which will be loaded as if it was an anon function in that scope.

Put it in a design doc, then only admin can make changes, out of the box.

Here is a nicer, but similar approach:

// Format, in db:
doc = {
   "_id": "_design/node",
   "your_function_name": {
       "arguments": [
           "nameOfArg1",
           "nameOfArg2"
       ],
       "code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);"
   },
   "your_other_function_name": {
       "arguments": [
           "name"
       ],
       "code": "console.log('hello', name, 'how\\'s it going, bro?');"
   }
};


var cradle = require('cradle');
var db = new(cradle.Connection)().database('db_name');

function run_from_db(name, args){
  db.get('_design/node', function (err, doc) {
    if (!err){
      if (doc[name] !== undefined){
        var fn = new Function(doc[name]['arguments'].join(','), doc[name].code);
        fn.apply(fn, args);
      }else{
        console.error("could not find", name, "in _design/node");
      }
    }else{
      console.error(err);
    }
  });
}


run_from_db('your_other_function_name', ['konsumer']);

this will output:

hello konsumer how's it going, bro?
like image 186
konsumer Avatar answered Feb 12 '23 11:02

konsumer