Common Lambda Actions
A collection of common operations done with AWS Lambda
Table of Contents
Intro
DynamoDB
Secrets Manager
Auth With Secrets Manager
Auth Without Secrets Manager
Responder
Schemas
Examples
Intro
This library aims to centralize your commonly performed actions. They are designed to reduce the amount of times you have to write the same get, put, functions for projects utilizing the AWS-SDK.
Responses {#intro-responses}
Almost of these helpers utilize promises. You must await the return of the promise to get the proper response
Errors {#intro-errors}
Returned errors will contain a standard and a custom property.
The standard is what is sounds like. The general description for the status code.
The custom will have any available message thrown by the error it originated from.
Example:
{
"standard": "Bad request",
"custom": "One of the required keys was not given a value"
}
DynamoDB
These are mainly wrappers around DynamoDB actions, abstracting as much as possible.
Get Item
Arguments
tableName | String | Name of the table you're searching |
key | Object | The key schema for the searched for item |
shouldLogParams | Boolean | Optional flag for logging the params before the operation |
Import Path
const { getItem } = require('simple-lambda-actions/dist/dynamo')
Response
Returns a promise, which will resolve to:
{
superImportantAttribute: 'YAAAAAASSSS'
}
Errors
400 | Bad Request | Usually thrown when you pass a tableName that cannot be found |
404 | Not Found | Thrown when the key schema provided did not match any records |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const getItem = require('simple-lambda-actions/dist/dynamo')
exports.handler = async event => {
const item = await getItem(tableName, keySchema)
}
Put Item
Arguments
tableName | String | Name of the table you're searching |
item | Object | The item you wish to write, must contain partition key |
shouldLogParams | Boolean | Optional flag for logging the params before the operation |
Import Path
const { putItem } = require('simple-lambda-actions/dist/dynamo')
Response
Returns a promise, which will resolve to an empty object. This comes directly from DynamoDB.
Errors
400 | Bad Request | Usually thrown when you pass a tableName that cannot be found, or if you omit a required key |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const putItem = require('simple-lambda-actions/dist/dynamo')
exports.handler = async event => {
await putItem(tableName, parsedBody, true)
}
Update Item
Arguments
tableName | String | Name of the table you're searching |
config | Object | The configuration for updating the record. Schema can be found here |
shouldLogParams | Boolean | Optional flag for logging the params before the operation |
Import Path
const { updateItem } = require('simple-lambda-actions/dist/dynamo')
Response
Returns a promise, which will resolve to an empty object. This comes directly from DynamoDB.
Errors
400 | Bad Request | Usually thrown when you pass a tableName that cannot be found, or if you omit a required key |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const updateItem = require('simple-lambda-actions/dist/dynamo')
exports.handler = async event => {
await updateItem(tableName, parsedBody, true)
}
Query Item
Arguments
params | Object | The params configuration for querying the records. Schema can be found here |
shouldLogParams | Boolean | Optional flag for logging the params before the operation |
Import Path
const { queryItem } = require('simple-lambda-actions/dist/dynamo')
Response
Returns a promise, which will resolve to the object containing the array of items meeting your criteria, as well as the counts.
{
"Items": [
{
}
],
"Count": 1,
"ScannedCount": 1
}
Errors
400 | Bad Request | Usually thrown when you pass a tableName that cannot be found, or if you omit a required key |
404 | Not Found | When no records match your provided query |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const queryItem = require('simple-lambda-actions/dist/dynamo')
exports.handler = async event => {
const items = await queryItem(params)
}
Transact Write
This library supports the following actions:
ConditionCheck
Delete
Put
Update
Arguments
operations | Array | Array of transactional operations. The expected schema can be found here |
shouldLogParams | Boolean | Optional flag for logging the params before the operation |
Import Path
const { transactWrite } = require('simple-lambda-actions/dist/dynamo')
Response
Returns a promise, which will resolve to an empty object.
Errors
400 | Bad Request | Usually thrown when you pass a tableName that cannot be found, or if you omit a required key |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const transactWrite = require('simple-lambda-actions/dist/dynamo')
const operationsConfig = [
{
operationType: 'update',
TableName: 'TEST_TABLE',
itemSpecificInfo: {
partitionKey: '...',
sortKey: '121212'
},
otherParams: {
UpdateExpression: 'set #a = :x + :y',
ConditionExpression: '#a < :MAX',
ExpressionAttributeNames: {'#a' : 'Sum'},
ExpressionAttributeValues: {
':x' : 20,
':y' : 45,
':MAX' : 100,
}
}
}
]
exports.handler = async event => {
try {
await transactWrite(operationsConfig)
} catch (error){
const { message, statusCode } = error
}
}
Authentication With Secrets Manager
These functions are integrated with Secrets Manager, and will fetch the signing key, then perform the auth action in one function call
Secret Validate Token
Arguments
secretId | String | The name of your secret key |
givenToken | String | The token you wish to validate |
Import Path
const { validateTokenWithSecretsManager } = require('simple-lambda-actions/dist/auth')
Response
Returns a promise, which will resolve to:
{
}
Errors
403 | Unauthorized | When the token is invalid, or not provided |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const { validateToken } = require('simple-lambda-actions/dist/auth')
const secretId = '...'
exports.handler = async event => {
const givenToken = event.headers.Authorization
const decodedPayload = await validateToken(secretId, givenToken)
}
Secret Generate Token
Arguments
secretId | String | ID of the secret key you will use to sign the token |
payloadToEncode | Object | What you wish to include inside of the token |
expiresIn | String | Duration of token validity. A more comprehensive solution can be found here and here |
Import Path
const { generateTokenWithSecretsManager } = require('simple-lambda-actions/dist/auth')
Response
Returns the token in the form of a string.
'eyasbdjbqjbh12312i7uebkjb'
Errors
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const { generateToken } = require('simple-lambda-actions/dist/auth')
const secretId = '...'
exports.handler = async event => {
const parsedBody = JSON.parse(event.body)
const expiresIn = '24h'
const decodedPayload = await generateToken(secretId, parsedBody, expiresIn )
}
Authentication Without Secrets Manager
These functions are standalone operations. They are the underlying blocks for the integration with Secrets Manager
Non Secret Validate Token
Arguments
token | String | The token you want to validate |
signingKey | String | The secret key you want to use to validate tokens |
Import Path
const { validateToken } = require('simple-lambda-actions/dist/auth/lib')
Response
Returns a promise, which will resolve to:
{
}
Errors
403 | Unauthorized | When the token is invalid, or not provided |
500 | Internal Error | Generic internal server error given when error does not provide code |
Example
const { validateToken } = require('simple-lambda-actions/dist/auth')
const signingKey = '...'
exports.handler = async event => {
const givenToken = event.headers.Authorization
const decodedPayload = await validateToken(givenToken, signingKey)
}
Schemas
Update Item Config
The following must be provided to the updateItem function as the config
Key | Object | The key schema of the item being updated | Key | Yes |
ExpressionAttributeNames | Object | How DynamoDB will reference the attribute name of the item being changed | Expression Name | Yes |
ExpressionAttributeValues | Object | How DynamoDB will reference the attribute value being changed | Expression Values | Yes |
UpdateExpression | String | This comma delimited list determines which operations are performed | Update Expression | Yes |
ReturnValues | String | | Update Expression | Yes |
Transact Write Operation
The following is the schema of a single operation inside of an array which will be executed sequentially in the transactWrite helper
operationType | String | Enum mapping for the type of operation the operation will be performing. Not case sensitive | delete | Yes |
TableName | String | Name of the table that this operation will be performed on | development-userTable | Yes |
itemSpecificInfo | Object | The data specific to this operation, such as primary key, or the item being written | Key or Item | Yes |
otherParams | Object | Other parameters specific to your operation that may be needed for the specific use case. | Update Expression, Expression Values, etc | No |
Query Items
The following is the schema for the params of querying items. If using a range ( sort ) key, all of the range parameters are required. You can however omit them, and just query based on the partition.
partitionKeyName | String | Name of the partition key on the table you're querying | emailAddress | Yes |
partitionKeySearchTerm | String | Value of partition key you are querying. MUST match exactly | yo.mama@lit.live | Yes |
rangeKeyName | String | Name of the range key on the table you're querying | role | No |
rangeKeySearchTerm | String | Value of range key you are querying | admin | No |
rangeKeyComparisonOperator | String | Enum of available comparison operators. List of supported options here | begins_with | No |
Examples
Various examples where space might have been limited
DynamoDB
Key Schema
{
"partitionKey": "yo ho, yo ho",
"rangeKey": "a pirates life for me"
}
Expression Attribute Name
In this example, #key_to_update represents the attribute you are targeting for change, where keyToUpdate is the actual attribute name.
Dynamo creates a reference to this key through the first value, and will use it to reference your item attribute.
{
"#key_to_update": "keyToUpdate",
}
Expression Attribute Values
In this example, :nv represents the new value in the same way Expression Name's work. :nv is mapped to newValue and will represent it in further operations
{
":nv": "newValue",
}
Update Expression
Here we are performing the set operation, on the key previously determined, setting the new value to the mapped result of :nv
const UpdateExpression = 'set #new_key = :nv,more...'
Supported Comparison Operators
More information can be found here
Currently the following operators are supported, anything else will throw an error.
The limiting factor is due to uniformity on how the condition expression is formulated.
=
<
>
<=
>=
attribute_exists
attribute_not_exists
begins_with
contains
Various examples where space might have been limited
DynamoDB
Key Schema
{
"partitionKey": "yo ho, yo ho",
"rangeKey": "a pirates life for me"
}
Expression Attribute Name
In this example, #key_to_update represents the attribute you are targeting for change, where keyToUpdate is the actual attribute name.
Dynamo creates a reference to this key through the first value, and will use it to reference your item attribute.
{
"#key_to_update": "keyToUpdate",
}
Expression Attribute Values
In this example, :nv represents the new value in the same way Expression Name's work. :nv is mapped to newValue and will represent it in further operations
{
":nv": "newValue",
}
Update Expression
Here we are performing the set operation, on the key previously determined, setting the new value to the mapped result of :nv
const UpdateExpression = 'set #new_key = :nv,more...'
Supported Comparison Operators
More information can be found here
Currently the following operators are supported, anything else will throw an error.
The limiting factor is due to uniformity on how the condition expression is formulated.
=
<
>
<=
>=
attribute_exists
attribute_not_exists
begins_with
contains