Skedulo functions (extensions)

Using back end API functionality to automate specific behavior in response to certain triggers.

Skedulo functions are back end APIs that can be written for a customer/organization.

Functions are Skedulo’s variant of the serverless API platform, and features stateless, authenticated APIs.

These can be used to build a backend for other components, such a web extensions or mobile pages. They are also useful for building integrations.

Serverless API

Functions are a way of automating specific behavior between different parts of the Skedulo backend in response to certain triggers.

For example, a customer wants an SMS to be sent to the job contact when the resource assigned to the job’s status changes to En Route.

To do this, you would do the following:

  • Create a webhook that fires each time a job status changes to En Route.
  • Direct the webhook to a connected function that receives the webhook payload as its input.
  • Trigger the API to send an SMS to the contact associated with the job.

Without Skedulo functions, users would need to create a public-facing API with their own servers to do this.

Create a function in a package

You can develop Skedulo functions within a package using the Skedulo Packages SDK.

  1. Create a new package or open an existing one in the Skedulo SDK. See Skedulo packages for more information.
  2. In the SDK package project, click Add Function.
  3. Provide the Name and Description of your function, then click Create Function Project.
  4. In the SDK package, click Develop on the function project to open the developer environment.
  5. Click Bootstrap to add any dependencies and validate the function.
  6. Click Start Development to start developing the function.

The SDK exposes the function both locally and remotely.

Routes

The /src/routes.ts file inside the function component folder handles navigation and routing.

The file looks like this:

import * as _ from 'lodash'
import * as pathToRegExp from 'path-to-regexp'

import { FunctionRoute } from '@skedulo/sdk-utilities'

// tslint:disable-next-line:no-empty-interface
interface RequestPayload {
}

export function getCompiledRoutes() {
  return getRoutes().map(route => {

    const regex = pathToRegExp(route.path)
  
    return {
      regex,
      method: route.method,
      handler: route.handler
    }
  })
}

function getRoutes(): FunctionRoute[] {
  return [
    {
      method: 'get',
      path: '/ping',
      handler: async (__, headers) => {

        const apiToken = headers.Authorization.split('Bearer')[1].trim()
        const apiServer = headers['sked-api-server']

        return {
          status: 200,
          body: { result: 'pong', apiServer, apiToken }
        }
      }
    },
    {
      method: 'post',
      path: '/action',
      handler: async (body: RequestPayload, headers) => {

        const apiToken = headers.Authorization.split('Bearer')[1].trim()
        const apiServer = headers['sked-api-server']

        return {
          status: 200,
          body: { apiToken, apiServer, requestBody: body }
        }
      }
    }
  ]
}

This defines a GET request with a /ping endpoint and a /action endpoint used for POST requests.

We use ngrok internally for this service.

This is not a hosted ngrok, however the ngrok is started on your local system, which is then valid for eight hours and can be used for development purposes.

Therefore, when doing localhost development, it is easier to use the localhost URL address rather than the hosted address, for example: GET http://localhost:52493/ping

GET /ping

You can copy the provided localhost URL and use it to make a GET request to the /ping endpoint to show that the server is running and accessible:

GET http://localhost:58543/SkeduloFunction/ping

This sends a request to the Skedulo API, which is then tunneled back to the localhost:

SDK ping

POST /action

The route.ts file also includes configuration for POST requests to the /action endpoint, for example:

POST http://localhost:58543/SkeduloFunction/action

You can provide a JSON body in the request and modify the route.ts file to print the output in the development window of the SDK by adding console.log(body) to the POST route in routes.ts.

For example, the following changes to route.ts permit a POST request that will print the JSON request body in the SDK console:

import * as _ from 'lodash'
import { RouteIterface } from './types'

export function getRoutes(): RouteIterface[] {

  return [
    {
      method: 'post',
      path: '/action',
      handler: async (body: RequestPayload[], headers) => {
        console.log(body)

        const apiToken = headers.Authorization.split('Bearer')[1].trim()
        const apiServer = headers['sked-api-server']

        return {
          status: 200,
          body: { apiToken, apiServer, requestBody: body }
        }
      }
    }
  ]
}

Add the following JSON payload in the POST request:

{
"hello": "world"
}

The SDK terminal shows the request payload printed with the successful POST operation:

SDK Post

Any changes that are logged from the Skedulo function development console are logged in the SDK window.

There is no terminal other than the development window.

Advanced functionality can be added using a Skedulo function, such as sending notifications to resources when a webhook hits the endpoint.


Last modified May 26, 2020: Corrected endpoint name (289c0e9)