hapi pal
Getting Started API Docs Best Practices hapi pal

Reference Version:

  • boilerplate
  • schwifty
  • schmervice
  • toys
  • lalalambda
  • ahem
  • avocat
  • hecks
  • hpal
  • hpal-debug
  • haute-couture
  • tandy
  • confidence
  • hodgepodge
  • underdog
github | npm

lalalambda

Serverless functions powered by hapijs

Build Status Coverage Status

Lead Maintainer - Devin Ivy

Installation

See further installation and setup instructions below for more information.

npm install @hapipal/lalalambda

Usage

See also the API Reference

Lalalambda is intended for use with hapi v19+, serverless v1 and v2, and nodejs v12+ (see v1 for lower support). Currently only deployments to AWS Lambda are supported, but we are open to expand support with your help!

Lalalambda offers three core features integrating hapi with the Serverless framework:

  1. ๐Ÿ—ป The ability to deploy an entire hapi server as a lambda function.

  2. ๐ŸŒ„ The ability to deploy individual hapi routes as lambda functions.

  3. ๐ŸŒ… The ability to deploy arbitrary lambda functions triggered by cloud events, authored similarly to how you'd create a standard hapi route.

Let's take a quick look at a code example for each of these features.

Examples

Lambda-ify an entire server

server.js
'use strict';

const Hapi = require('@hapi/hapi');
const Lalalambda = require('@hapipal/lalalambda');

exports.deployment = async () => {

    const server = Hapi.server();

    await server.register({
        plugin: Lalalambda,
        options: {
            lambdaify: true // Creates a lambda named "server" by default
        }
    });

    server.route({
        method: 'get',
        path: '/hello/{name?}',
        handler: ({ params }) => {

            return {
                hello: params.name || 'world'
            };
        }
    });

    return server;
};

Assuming you've already followed installation, now just deploy to get a URL to your hapi server deployed as a lambda function!

npx serverless deploy

Lambda-ify a single hapi route

server.js
'use strict';

const Hapi = require('@hapi/hapi');
const Lalalambda = require('@hapipal/lalalambda');

exports.deployment = async () => {

    const server = Hapi.server();

    await server.register(Lalalambda);

    server.route({
        method: 'get',
        path: '/hello/{name?}',
        options: {
            // By default the route id is used to name your lambda
            id: 'hello',
            plugins: {
                lalalambda: true
            },
            handler: ({ params }) => {

                return {
                    hello: params.name || 'world'
                };
            }
        }
    });

    return server;
};

Assuming you've already followed installation, now just deploy to get a URL to your hapi route deployed as a lambda function!

npx serverless deploy

Create an arbitrary lambda function

Here we'll create a lambda that is scheduled to log the most recent earthquake on Earth each minute.

server.js
'use strict';

const Hapi = require('@hapi/hapi');
const Wreck = require('@hapi/wreck');
const Lalalambda = require('@hapipal/lalalambda');

exports.deployment = async () => {

    const server = Hapi.server({
        debug: {
            // These hapi server logs will show-up in your lambda's logs
            log: ['earthquake']
        }
    });

    await server.register(Lalalambda);

    // Just as simple as configuring a route!

    server.lambda({
        id: 'earthquakes',
        options: {
            events: [{
                schedule: 'rate(1 minute)'
            }],
            handler: async (event, context) => {

                const { payload } = await Wreck.get('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson');

                const { features: [earthquake] } = JSON.parse(payload.toString());

                if (earthquake) {
                    // You have access to the server on the event's context
                    context.server.log('earthquake', earthquake.properties.title);
                }
            }
        }
    });

    return server;
};

Assuming you've already followed installation, now just deploy to start logging earthquake data! You can then view these logs in realtime from your terminal.

npx serverless deploy
npx serverless logs --tail --function earthquakes

Installation and setup

Lalalambda is one package that doubles as 1. a hapi plugin and 2. a Serverless framework plugin. These two plugins work together to allow you to define lambda functions in hapi that can be packaged and deployed using the Serverless framework to AWS Lambda. A basic installation has just a few steps.

  1. Install the lalalambda and serverless packages from npm.

    npm install @hapipal/lalalambda
    npm install --save-dev serverless
  2. Setup a Serverless config in the root of your project including lalalambda as a plugin.

    # serverless.yml
    service: my-service
    
    provider:
      name: aws
      runtime: nodejs12.x
    
    plugins:
      - '@hapipal/lalalambda'

    There is also an optional configuration for declaring the path to the server file.

    # serverless.yml
    
    custom:
      lalalambda:
        serverPath: 'src/my-server.js'  # This is always relative to the serverless.yml file.
  3. Register lalalambda to your hapi server.

    If you're using the pal boilerplate then simply add lalalambda to your manifest's plugins section.

    await server.register(require('@hapipal/lalalambda'));
  4. Ensure server.js or server/index.js exports a function named deployment that returns your configured hapi server. Note that the server may be initialized but should not be started.

    If you're using the pal boilerplate then you can skip this step!

    Below is a very simple example of boilerplate code to configure a hapi server, and is not necessarily "production-ready." For a more complete setup, consider using the pal boilerplate, or check-out its approach as seen here.

    // server.js
    'use strict';
    
    const Hapi = require('@hapi/hapi');
    const Lalalambda = require('@hapipal/lalalambda');
    const AppPlugin = require('./app');
    
    // Lalalambda will look for and use exports.deployment()
    // as defined below to obtain a hapi server
    
    exports.deployment = async ({ start } = {}) => {
    
        const server = Hapi.server();
    
        await server.register(Lalalambda);
    
        // Assuming your application (its routes, lambdas, etc.) live in a plugin
        await server.register(AppPlugin);
    
        if (start) {
            await server.start();
            console.log(`Server started at ${server.info.uri}`);
        }
    
        return server;
    };
    
    // Start the server only when this file is
    // run directly from the CLI, i.e. "node ./server"
    
    if (!module.parent) {
        exports.deployment({ start: true });
    }

Now you have the full expressiveness of the Serverless and hapi frameworks at your fingertips!

The rest of your setup depends on however you want to further configure Serverless and hapi. We suggest checking-out the Serverless AWS Guide, continuing by taking a peek at the Credentials section so that the Serverless CLI will have access to deploy to your AWS account. Going forward you can invoke the Serverless CLI for deployment, etc.:

npx serverless --help
# or, shorthand:
npx sls --help

API

Serverless functions powered by hapijs

Note

Lalalambda is intended for use with hapi v19+, serverless v1 and v2, and nodejs v12+ (see v1 for lower support).

Lalalambda is one package that doubles as 1. a hapi plugin and 2. a Serverless framework plugin. These two plugins work together to allow you to define lambda functions in hapi that can be packaged and deployed using the Serverless framework to AWS Lambda.

The hapi plugin

The hapi plugin is responsible for the interface to,

  1. Configure an entire hapi server for deployment as a lambda function using plugin registration options.
  2. Configure individual hapi routes for deployment as lambda functions using route configuration.
  3. Configure arbitrary lambda functions triggered by cloud events using server.lambda().

Registration

Lalalambda may be registered multiple timesโ€”it should be registered in any plugin that would like to use any of its features.

It only has one plugin registration option, which is used to configure the entire hapi server as a lambda function. Although lalalambda may be registered multiple times, it may only be registered once using this option.

  • lambdaify - a lambda configuration as described in server.lambda(lambda) below. Alternatively, may be a string serving as the lambda config id. Note that the lambda config events may also be a function that receives the default configuration and returns the desired configuration. When this option is set to true it defaults to the lambda config { id: 'server' }.

Example

await server.register({
    plugin: require('@hapipal/lalalambda'),
    options: {
        lambdaify: true
    }
})

Route configuration

Individual hapi routes can be configured as lambda functions.

route.options.plugins.lalalambda

A lambda configuration as described in server.lambda(lambda) below. Alternatively, may be a string serving as the lambda config id. Note that the lambda config events may also be a function that receives the default configuration and returns the desired configuration. When this option is set to true it defaults to the lambda config with id matching the hapi route's route.options.id.

Example

server.route({
    method: 'get',
    path: '/hello/{name?}',
    options: {
        id: 'hello',
        plugins: {
            lalalambda: true
        },
        handler: ({ params }) => {

            return {
                hello: params.name || 'world'
            };
        }
    }
});

server.lambda(lambda)

Defines a lambda function to be merged into the project's Serverless functions config where,

  • lambda - a lambda configuration object or an array of configuration objects where each object contains:
    • id - (required) the lambda id.
    • handler - (required when options.handler is not set) an alternative to using options.handler, described below.
    • options - the lambda configuration:
      • events, runtime, etc. - any configuration item described in the Serverless functions config.

      • handler - (required) the lambda function's handler async function(event, context):

        • The event and context arguments are described in the AWS Lambda docs. The context object also contains context.server referencing the hapi server in which the lambda was defined. If server.bind() was called, the handler will be bound to the provided context via this. Note that handlers never use callbacks.

Example

const Wreck = require('@hapi/wreck');

server.lambda({
    id: 'earthquakes',
    options: {
        events: [{
            schedule: 'rate(1 minute)'
        }],
        handler: async (event, context) => {

            const { payload } = await Wreck.get('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson');

            const { features: [earthquake] } = JSON.parse(payload.toString());

            if (earthquake) {
                // You have access to the server on the event's context
                context.server.log('earthquake', earthquake.properties.title);
            }
        }
    }
});

The Serverless plugin

Currently the plugin only supports the aws Serverless provider, and each function deployed via lalalambda must use the nodejs8.10 runtime or newer (nodejs12.x is recommended). The plugin is responsible for:

  1. Configuring the project's Serverless service based upon relevant lambda and route configurations made within hapi.

  2. Writing lambda handler files during packaging, deployment, local invocation, etc., and later cleaning them up. These files will be written in your project root's _lalalambda/ directory.

In order to interoperate with your hapi server, it is expected that server.js or server/index.js export an async function named deployment returning your configured hapi server. This server should have the lalalambda hapi plugin registered, and it may be initialized but should not be started. The path to server.js can also be customized through the custom.lalalambda config section as shown below.

A minimal Serverless config utilizing lalalambda will look like this:

# serverless.yml
service: my-service

provider:
  name: aws
  runtime: nodejs12.x

plugins:
  - '@hapipal/lalalambda'

# optional
custom:
  lalalambda:
    serverPath: some/relative/path/to/server.js
Hapi Pal
Home
API Docs Best Practices
Helpful Links
Discussion Board Code of Conduct Edit This Site Slack (#hapipal) Medium Blog Designer, Justin Varberakis hapi.dev
Made with in Portland, Maine