mountebank icon indicating copy to clipboard operation
mountebank copied to clipboard

Feature request for having decorate be a local "node" function.

Open plee-nm opened this issue 8 years ago • 2 comments

Why

Make it easier to define complex behaviors in javascript.

From my understanding the decorate behavior must be a single line function with no external variables. This makes it hard inject any non-trival behavior. It would be nice to be able to pass in a string reference to a local function which can be required by a naming convention. I can work on a pr with it requiring a path local to the current running process.

How

For example if decorate is set to injectScriptToHtml

It would could do something like:

const {join} = require('path');
const fns = require(process.cwd(), 'mbBehaviors');

exports.getDecoratorFn = function (functionName) {
  return fns[name];
}

Then behaviors.js would just have to change to allow local functions to be called.

https://github.com/bbyars/mountebank/blob/master/src/models/behaviors.js#L225

 try {
            var locaFn = getDecoratorFn(fn);
           if(localFn) {
                 result = localFn(request, response, logger);
          }
         else { 
                  result = eval(injected);
         }

//local behaviors that the end user would have on their machine/repo

const cheerio = require('cheerio')
exports.injectScriptToHtml = function(request, response, logger) {
   const $ = cheerio.load(response.body)
   $.add('head', ...
  response.body = $.html()
}

Does this seem like something worth doing? The other two approaches right now require a complex almost near impossible build process to build a single line function that can be eval'd properly or write a shell script in node that read vars in, calls the js function and returns the result to stdout.

plee-nm avatar Jul 11 '17 22:07 plee-nm

Yes, this does look valuable. Happy to accept a PR if you're interested. Thanks for the suggestion.

(One note - I've indexed versions of node that mountebank supports to those still on node's LTS schedule, which at the moment bottoms at out v4. The only reason that matters is that I believe v4 doesn't support a lot of the ES6 syntax like the object destructuring you used above. That doesn't matter for the local function, obviously, as the user can run whatever version of node they want, but it matters for any code added to the core of mountebank since I haven't wired up Babel or anything similar to transpile).

bbyars avatar Jul 22 '17 18:07 bbyars

@bbyars I still think this feature would be nice to have but I finally needed to have a conditional response and I was able to do it with a relatively decent hack. I was able to define a function locally that uses libraries, external functions, etc and then require it in the function definition string.

const inject = `(request, state, logger) => require('${__dirname}/conditionalResponse')(request,state,logger)`;
// conditionalResponse.js
module.exports = (request, state, logger) => {
    return {
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ count: state.requests })
    };
}

This is working because require(/full/path/to/file will work anywhere and __dirname returns a full path.

plee-nm avatar Jan 25 '19 22:01 plee-nm