DEV Community

Tim Ermilov
Tim Ermilov

Posted on

Exoframe v5.0 - simplifying js function deployments

Exoframe is a self-hosted tool that allows simple one-command deployments using Docker.
If you've never heard about it, you can read more here or see it in action here.

And today I'm happy to release Exoframe v5.0 that adds support for simple javascript functions deployments in one command.

Currently, Exoframe supports 4 types of javascript functions:

  • HTTP functions - your typical HTTP request handler
  • Worker functions - anything that has to run in the background (e.g. bots, repeated tasks, etc)
  • Trigger functions - your own triggers that can invoke custom functions
  • Custom functions - handlers for your custom triggers

Here's a quick example walkthroughs that demonstrate creation of each type of functions.

Creating HTTP function

First, let's write the function itself.
Exoframe will require whole function folder so make sure to either call your file index.js or to include package.json that points to your main file.
In this case, let's touch index.js and write the following code in it:

// index.js
module.exports = async (event, context) => {
  // use context.log to provide logs to exoframe
  // those logs can be then accessed from exoframe CLI
  context.log('test log');
  context.log('other log');

  // you can just return a value
  return `hello world`;

  // alternatively you can use reply prop
  // to directly access Fastify reply object
  context.reply.code(200).send('hello world!');
  // make sure to return false-y value if you do this
  // so exoframe doesn't try to send the response second time
  return false;
};

Note the usage of context.log for logging. Doing so will allow you to get logs from your function using exoframe logs your-function-name command.

Next, we need to generate new Exoframe config for your function.
To do that, simply execute:

$ exoframe init -f

This will generate a config that looks like this:

{
  "name": "test-function",
  "function": true
}

By default, Exoframe considers functions to be HTTP functions and will route them to /${config.name} - so, /test-function in our case.
This can be changed by editing the config to include route property, e.g.:

{
  "name": "test-function",
  "function": {
    "route": "test"
  }
}

Now you can deploy your function using Exoframe by simply running exoframe deploy!

Creating worker function

Once again, let's start with the function itself.
Let's touch index.js and write the following code in it:

// index.js
module.exports = async (_, context) => {
  // use context.log to log stuff, just as in HTTP function
  context.log('Worker started.');
  // worker can execute any long-running task you want
  let counter = 0;
  setInterval(() => {
    context.log(`Worker: ${counter++}`);
  }, 1000);
};

After that we want to generate Exoframe config in the same manner as for HTTP function, but then we'll need to modify it to include new type property, like so:

{
  "name": "test-worker",
  "function": {
    "type": "worker"
  }
}

This will tell Exoframe it should start current function in a separate Worker Thread.
And now your worker function is ready for deployment!

Creating trigger function

And again, let's start with the function itself.
Let's touch index.js and write the following code in it:

module.exports = async (dispatchEvent, context) => {
  // log
  context.log('Trigger started.');

  // in this case we trigger all subscribed functions every 1s
  const interval = setInterval(() => {
    context.log(`Triggering!`);
    // dispatching new events to all function with data
    dispatchEvent({data: 'hello world!'});
  }, 1000);

  // trigger function should return a cleanup function
  return () => {
    clearInterval(interval);
  };
};

Note that your trigger needs to return a cleanup function that, well, does the cleanup once you remove the function from your server.

After that, you'll need to generate a config file and edit it to include type property set to trigger, like so:

{
  "name": "test-trigger",
  "function": {
    "type": "trigger"
  }
}

That's it, your trigger is ready to be deployed!

Creating custom handler function

Finally, let's see how you can create custom handlers for your triggers.
Let's write that index.js once again:

module.exports = async (event, context) => {
  // Will get custom data from trigger above, so logging will say:
  // Custom function triggered: {"data": "hello world!"}
  context.log(`Custom function triggered: ${JSON.stringify(event.data)}`);
};

Now we need to tell Exoframe that our current function should react to our custom trigger. This is done by using type property and assigning a value equal to the name of our custom trigger, like so:

{
  "name": "test-triggered-fn",
  "function": {
    "type": "test-trigger"
  }
}

And now you can deploy your custom handler!

That's it!

That covers all the basics with regards to working with functions in Exoframe.
You can find more detailed info in Exoframe docs.

Try it out and let me know what you think!

Top comments (0)