/**
 * Run a single Canvas function.
 *
 * @param {*} server - The Kibana server object
 * @param {*} handlers - The Canvas handlers
 * @param {*} fnCall - Describes the function being run `{ functionName, args, context }`
 */
async function runFunction(server, handlers, fnCall) {
  const { functionName, args, context } = fnCall;
  const types = server.plugins.interpreter.types.toJS();
  const { deserialize } = serializeProvider(types);
  const fnDef = server.plugins.interpreter.serverFunctions.toJS()[functionName];

  if (!fnDef) {
    throw Boom.notFound(`Function "${functionName}" could not be found.`);
  }

  return fnDef.fn(deserialize(context), args, handlers);
}
Example #2
0
  io.on('connection', async socket => {
    // 'request' is the modified hapi request object
    const request = await getModifiedRequest(server, socket);
    if (!request) return; // do nothing without the request object

    const types = server.plugins.interpreter.types.toJS();
    const { serialize, deserialize } = serializeProvider(types);

    // I'd love to find a way to generalize all of these, but they each need a different set of things
    // Note that ORDER MATTERS here. The environments will be tried in this order. Do not reorder this array.
    const routeExpression = routeExpressionProvider([
      thread({ onFunctionNotFound, serialize, deserialize }),
      serverEnv({ onFunctionNotFound, request, server }),
      browser({ onFunctionNotFound, socket, serialize, deserialize }),
    ]);

    function onFunctionNotFound(ast, context) {
      return routeExpression(ast, context);
    }

    socket.on('getFunctionList', () => {
      socket.emit('functionList', server.plugins.interpreter.serverFunctions.toJS());
    });

    socket.on('run', async ({ ast, context, id }) => {
      try {
        const value = await routeExpression(ast, deserialize(context));
        socket.emit(`resp:${id}`, { type: 'msgSuccess', value: serialize(value) });
      } catch (err) {
        // TODO: I don't think it is possible to hit this right now? Maybe ever?
        socket.emit(`resp:${id}`, { type: 'msgError', value: err });
      }
    });

    socket.on('disconnect', () => {
      // remove all listeners on disconnect
      socket.removeAllListeners();
    });
  });