Skip to content

codemonger-io/mapping-template-compose

Repository files navigation

English / 日本語

Mapping Template Compose

Makes Amazon API Gateway's mapping template composable.

This library is especially powerful if you combine it with AWS Cloud Development Kit.

Installing this library

npm install https://github.com/codemonger-io/mapping-template-compose.git#v0.2.0

Installing from GitHub Packages

Every time commits are pushed to the main branch, a developer package is published to the npm registry managed by GitHub Packages. A developer package bears the next release version number but followed by a dash (-) plus the short commit hash; e.g., 0.2.0-abc1234 where abc1234 is the short commit hash of the commit used to build the package (snapshot). You can find developer packages here.

Configuring a GitHub personal access token

To install a developer package, you need to configure a classic GitHub personal access token (PAT) with at least the read:packages scope. Below briefly explains how to configure a PAT. Please refer to the GitHub documentation for more details.

Once you have a PAT, please create a .npmrc file in your home directory with the following content:

//npm.pkg.github.com/:_authToken=$YOUR_GITHUB_PAT

Please replace $YOUR_GITHUB_PAT with your PAT.

In the root directory of your project, please create a .npmrc file with the following content:

@codemonger-io:registry=https://npm.pkg.github.com

Then you can install a developer package with the following command:

npm install @codemonger-io/mapping-template-compose@0.2.0-abc1234

Please replace abc1234 with the short commit hash of the snapshot you want to install.

Motivation

Have you ever felt that describing mapping templates for Amazon API Gateway is cumbersome? I got tired of writing mapping templates because:

  1. I had to write a lot of boilderplate code; e.g., extracting a query parameter as a property:

    "username": "$util.escapeJavaScript($util.urlDecode($input.params("username"))).replaceAll("\\'", "'")"
  2. It was difficult to reuse components of mapping templates

Regarding the second issue, the major difficulty is in making sure a JSON representation resulting from a mapping template valid.

Suppose you have the following property definitions as components:

const username = `"username": "$util.escapeJavaScript($util.urlDecode($input.params("username"))).replaceAll("\\'", "'")"`;
const signature = `"signature": $input.json("$.signature")`;
const date = `"date": "$util.escapeJavaScript($util.urlDecode($input.params("date"))).replaceAll("\\'", "'")"`;

If we want to construct a simple object that has all the above properties:

{
  "username": "$util.escapeJavaScript($util.urlDecode($input.params("username"))).replaceAll("\\'", "'")",
  "signature": $input.json("$.signature"),
  "date": "$util.escapeJavaScript($util.urlDecode($input.params("date"))).replaceAll("\\'", "'")"
}

You have to omit a trailing comma after the last property date, though, this is rather straightforward:

`{
  ${[username, signature, date].join(',\n  ')}
}`

What if all the properties may be omitted? You might come up with the following code:

`{
#if ($input.params('username') != "")
  ${username},
#end
#if ($input.json('$.signature') != "")
  ${signature},
#end
#if ($input.params('date') != "")
  ${date}
#end
}`

Unfortunately, the above template does not always produce a valid JSON object. It will end up with a dangling comma if date is omitted.

{
  "username": "<username>",
  "signature": "<signature>",
}

We have do something like below:

`{
#if ($input.params('username') != "")
  ${username}
#end
#if ($input.json('$.signature') != "")
#if ($input.params('username') != "")
  ,
#end
  ${signature}
#end
#if ($input.params('date') != "")
#if (($input.params('username') != "") || ($input.json('$.signature') != ""))
  ,
#end
  ${date}
#end
}`

It is daunting, isn't it? This library is intended to relieve the pain of writing mapping templates like the above.

Example

You can rewrite the example in the previous section with this library into:

import { composeMappingTemplate, ifThen } from '@codemonger-io/mapping-template-compose';

composeMappingTemplate([
  ifThen(
    '$input.params("username") != ""',
    [['username', `"$util.escapeJavaScript($util.urlDecode($input.params("username"))).replaceAll("\\'", "'")"`]],
  ),
  ifThen(
    '$input.json("signature") != ""',
    [['signature', '$input.json("$.signature")']],
  ),
  ifThen(
    '$input.params("date") != ""',
    [['date', `"$util.escapeJavaScript($util.urlDecode($input.params("date"))).replaceAll("\\'", "'")"`]],
  ),
]);

You can make it further modular:

import { type KeyValue, composeMappingTemplate, ifThen } from '@codemonger-io/mapping-template-compose';

const username: KeyValue = ['username', `"$util.escapeJavaScript($util.urlDecode($input.params("username"))).replaceAll("\\'", "'")"`];
const signature: KeyValue = ['signature', '$input.json("$.signature")'];
const date: KeyValue = ['date', `"$util.escapeJavaScript($util.urlDecode($input.params("date"))).replaceAll("\\'", "'")"`];
const optionalUsername = ifThen('$input.params("username") != ""', [username]);
const optionalSignature = ifThen('$input.json("signature") != ""', [signature]);
const optionalDate = ifThen('$input.params("date") != ""', [date]);

composeMappingTemplate([
  optionalUsername,
  optionalSignature,
  optionalDate,
]);

What mapping template can we compose?

What this library specifically does is only one thing: to determine where to place a comma (","). However, this seemingly trivial task turns out complicated as you can see in the example in Section "Motivation". Thus, not all of the possible patterns in mapping templates are supported. For instance, looping is not supported yet. Please refer to supported-patterns.md for what mapping template you can compose with this library.

API documentation

You can find the API documentation in ./api-docs/markdown folder.

Development

Resolving dependencies

pnpm install --frozen-lockfile

Building

pnpm build

Testing

pnpm test

Generating the API documentation

pnpm build:doc

About

Make Amazon API Gateway's mapping template composable

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •