0.1.4 • Published 12 days ago

obelisk-lambda v0.1.4

Weekly downloads
-
License
MIT
Repository
-
Last release
12 days ago

Όbelisk λ

A powerful request router for "monolithic" Lambdas.

Obelisk is powered by find-my-way - used by Fastify and Restify. Obelisk adopts route-matching from find-my-way and provides a more Lambda-like interface for handlers.

Install

Make sure you actually want a "fat function", then:

npm i obelisk-lambda

Requires Node.js v18+ (v16 works, but isn't recommended).

Usage

lambda.js:

import { ObeliskRouter } from "obelisk-lambda";

const router = new ObeliskRouter();

router.on(
  "GET",
  "/things/near/:lat-:lng/radius/:r",
  async ({ params, store, searchParams }) => {
    const { lat, long, r } = params

    // use coordinates and r (radius) to find the thing

    return {
      statusCode: 200,
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ params, store, searchParams }),
    };
  },
);

export const handler = router.mount();

A more elaborate router can be found in ./example/src/http/any-catchall/router.mjs

Deployment

The deploy target is an AWS Lambda behind a v2 HTTP API Gateway1.

These sort of HTTP Lambdas can easily deployed with Architect -- see ./example for a sample Arc project2.

1 v1 REST API Gateways are not supported. Read about API Gateway v2 Lambda integration.

2 Obelisk is not currently compatible with Arc's Node.js helper library: @architect/functions. Specifically the http() and http.async() methods.

API

Constructor

Create a new Obelisk router.

defaultRoute is optional

Similar to find-my-way, you can specify a default handler that will be invoked when no route is matched or a matched route does not return.

function defaultRoute ({ event, context, params, searchParams, store }) {
  // event and context are always available
  // params, searchParams, and store are only available if a route was matched
  console.log("defaultRoute", event.rawPath);

  return {
    statusCode: 404,
    headers: { "content-type": "text/plain; charset=utf8" },
    body: "not found.",
  };
}

const router = new ObeliskRouter({ defaultRoute });

Instance Methods

on(method, path, [options], handler, [store])

Add a route to a router instance. See find-my-way's docs on method and path.

Note that handler functions are quite different from find-my-way. See Handlers API below.

router.on("GET", "/things/:id", ({ params }) => {
  const { id } = params;

  return {
    statusCode: 200,
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ thingId: id }),
  };
});

options are optional.

on() tries to maintain find-my-way's method signature.

The optional store is not managed in the same way as find-my-way and will likely change in the future.

mount()

Create a Lambda handler function from the Obelisk router.

prettyPrint()

Calls the internal router's prettyPrint method to return an ASCII diagram of known routes.

Instance Properties

These are mostly used internally and likely not helpful to developers at runtime. They are exposed for debugging purposes.

defaultRoute

The original defaultRoute passed into the constructor.

handlers

A Map of registered routes keyed by the value returned when registering a route.

router

The internal FindMyWay router instance.
Note: provided route handlers are not actually registered with router.router and are managed in router.handlers.

Handlers API

Payload

event API Gateway 2.0 Event

Reference: Working with AWS Lambda proxy integrations for HTTP APIs

context Lambda Context

Reference: AWS Lambda context object in Node.js

params FindMyWay parsed path params

router.on(
  "GET",
  "/things/near/:lat-:lng/radius/:r",
  async ({ params }) => {
    const { lat, lng, r } = params;
    const thing = await things.geoFind({ lat, lng }, r);
    
    return {
      statusCode: 200,
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ thing }),
    };
  },
);

searchParams FindMyWay's parsed search params

router.on("GET", "/search", async ({ searchParams }) => {
  const { q } = searchParams

  // GET /search?rating=5&sale=true
  // q == { rating: '5', sale: 'true' }

  const results = await things.search({ query: q })

  return {
    statusCode: 200,
    headers: { "content-type": "text/html; charset=utf8" },
    body: renderSearchResults(results),
  };
});

store FindMyWay store

The store is currently passed through but not entirely functional as in find-my-way.

FAQ

  1. IMO ordered arguments are a bummer
  2. res isn't as simple as returning data
  3. a payload with many keys means Obelisk can easily attach AWS-provided data

function (req, res) {} has, and will continue, to serve long-lived Node processes well, but structured payloads are more ergonomic for evented "cloud functions".

Decode the base64 body on the event. Assuming the body was sent as x-www-form-urlencoded (HTML forms are):

import { parse } from "node:querystring"; // or your query string parser of choice

router.on("POST", "/form", ({ event }) => {
  // `event` is an APIGatewayProxyEventV2
  const data = Buffer.from(event.body, "base64").toString("utf8");
  const decoded = parse(data);
  // ...

If the original request doesn't match a route, defaultRoute is invoked with only the event and context objects.

In find-my-way it is used to persist data when the route is registered and/or between handlers. This feature is only partially implemented in Obelisk.

0.1.4

12 days ago

0.1.3

6 months ago

0.1.2

8 months ago

0.1.1

8 months ago

0.1.0

8 months ago

0.0.2

12 months ago

0.0.1

12 months ago