aws-core-utils v7.0.2
Core utilities for working with Amazon Web Services (AWS), including ARNs, regions, stages, Lambdas, AWS errors, stream events, Kinesis, DynamoDB.DocumentClients, etc.
Currently includes:
- api-lambdas.js
- Utilities for working with Lambdas exposed to AWS API Gateway, including functions to:
- Configure a standard context for AWS Gateway exposed Lambdas (re-exported from contexts.js module)
- Fail Lambda callbacks with standard AppError errors to facilitate mapping of errors to HTTP status codes on API Gateway.
- arns.js
- Utilities for working with Amazon Resource Names (ARNs)
- aws-errors.js
- Utilities for working with AWS errors
- contexts.js
- Utilities for configuring contexts for AWS Gateway exposed and other types of Lambdas
- dynamodb-doc-client-cache.js
- A module-scope cache of AWS.DynamoDB.DocumentClient instances by region for Lambda.
- dynamodb-doc-client-utils.js
- Utilities for working with AWS DynamoDB.DocumentClient.
- dynamodb-utils.js
- Utilities for working with AWS DynamoDB.
- kinesis-cache.js
- A module-scope cache of AWS.Kinesis instances by region for Lambda.
- kms-cache.js
- A module-scope cache of AWS.KMS instances by region for Lambda usage.
- kms-utils.js
- Utilities to simplify working with AWS.KMS instances.
- lambda-cache.js
- A module-scope cache of AWS.Lambda instances by region for use within Lambda functions.
- lambda-utils.js
- Utilities to simplify working with an AWS.Lambda instance
- lambdas.js
- Utilities for working with AWS Lambda, which enable extraction of function names, versions and, most importantly,
aliases from AWS contexts and their invoked function ARNs.
- Utility for failing non-API Gateway Lambda's callbacks with standard AppError errors if mapping of errors to HTTP status codes is needed
- regions.js
- Utilities for resolving the AWS region from various sources (primarily for AWS Lambda usage).
- stages.js
- Utilities for resolving or deriving the current stage (e.g. dev, qa, prod) from various sources
(primarily for AWS Lambda usage).
- Utilities for configuration of stage handling.
- Configurable and default functions for generating stage-qualified stream and resource names.
- Configurable and default functions for extracting stages from stage-qualified stream and resource names.
- stream-events.js
- Utilities for extracting information from AWS Kinesis and AWS DynamoDB stream events.
This module is exported as a Node.js module.
Installation
Using npm:
$ {sudo -H} npm i -g npm
$ npm i --save aws-core-utils
In Node.js:
- To use the
api-lambdas
module within your API Gateway exposed Lambda:
const apiLambdas = require('aws-core-utils/api-lambdas');
const appErrors = require('core-functions/app-errors');
const BadRequest = appErrors.BadRequest;
const context = {};
const standardOptions = require('my-options.json');
const standardSettings = undefined;
function exampleFunction(event, context) { }
module.exports.handler = apiLambdas.generateHandlerFunction(context, standardSettings, standardOptions, exampleFunction);
module.exports.handler = apiLambdas.generateHandlerFunction(context, standardSettings, standardOptions, exampleFunction, 'info',
[400, 404, 500], 'Invalid request ...', 'Failed to ...', 'Finished ...');
module.exports.handler = (event, awsContext, callback) => {
const context = {};
try {
apiLambdas.configureStandardContext(context, standardSettings, standardOptions, event, awsContext);
exampleFunction(event, context)
.then(response => {
context.info('Finished ...');
callback(null, response);
})
.catch(err => {
if (err instanceof BadRequest || appErrors.getHttpStatus(err) === 400) {
context.warn('Invalid request ...' + err.message);
} else {
context.error('Failed to ...', err.stack);
}
apiLambdas.failCallback(callback, err, awsContext);
});
} catch (err) {
context.error('Failed to ...', err.stack);
apiLambdas.failCallback(callback, err, awsContext);
}
};
apiLambdas.failCallback(callback, err, awsContext, 'My error msg', 'MyErrorCode', [400, 404, 418, 500, 508]);
- To use the AWS ARN utilities
const arns = require('aws-core-utils/arns');
const arnComponent = arns.getArnComponent(arn, index);
const arnPartition = arns.getArnPartition(arn);
const arnService = arns.getArnService(arn);
const arnRegion = arns.getArnRegion(arn);
const arnAccountId = arns.getArnAccountId(arn);
const arnResources = arns.getArnResources(arn);
- To use the AWS errors utilities
const awsErrors = require('aws-core-utils/aws-errors');
- To use the
contexts.js
module:
const contexts = require('aws-core-utils/contexts');
const context = {};
const standardOptions = require('my-standard-options.json');
const standardSettings = {};
contexts.configureStandardContext(context, standardSettings, standardOptions, awsEvent, awsContext);
const myCustomSettings = {myCustomSetting1: 1, myCustomSetting2: 2, myCustomFunction: () => {}};
console.log(`Irrelevant logging - only added to avoid unused function warning - ${myCustomSettings.myCustomFunction()}`);
const myCustomOptions = require('my-custom-options.json');
contexts.configureCustomSettings(context, myCustomSettings, myCustomOptions);
console.log(`context.custom = ${JSON.stringify(context.custom)}; myCustomFunction = ${JSON.stringify(context.custom.myCustomFunction)} `);
- To use the DynamoDB.DocumentClient cache to configure and cache an AWS DynamoDB.DocumentClient instance per region
const dynamoDBDocClientCache = require('aws-core-utils/dynamodb-doc-client-cache');
const context = {};
const logging = require('logging-utils');
logging.configureLogging(context);
const dynamoDBDocClientOptions = {
maxRetries: 0
};
const dynamoDBDocClient = dynamoDBDocClientCache.setDynamoDBDocClient(dynamoDBDocClientOptions, context);
dynamoDBDocClientCache.configureDynamoDBDocClient(context, dynamoDBDocClientOptions);
console.log(context.dynamoDBDocClient);
const dynamoDBDocClient1 = dynamoDBDocClientCache.getDynamoDBDocClient();
const dynamoDBDocClient2 = dynamoDBDocClientCache.getDynamoDBDocClient('us-west-2');
const optionsUsed1 = dynamoDBDocClientCache.getDynamoDBDocClientOptionsUsed();
const optionsUsed2 = dynamoDBDocClientCache.getDynamoDBDocClientOptionsUsed('us-west-1');
const deleted = dynamoDBDocClientCache.deleteDynamoDBDocClient('eu-west-1');
- To use the Kinesis cache to configure and cache an AWS Kinesis instance per region
const kinesisCache = require('aws-core-utils/kinesis-cache');
const context = {};
const logging = require('logging-utils');
logging.configureLogging(context);
const kinesisOptions = {
maxRetries: 0
};
const kinesis = kinesisCache.setKinesis(kinesisOptions, context);
kinesisCache.configureKinesis(context, kinesisOptions);
console.log(context.kinesis);
const kinesis1 = kinesisCache.getKinesis();
const kinesis2 = kinesisCache.getKinesis('us-west-2');
const optionsUsed1 = kinesisCache.getKinesisOptionsUsed();
const optionsUsed2 = kinesisCache.getKinesisOptionsUsed('us-west-1');
const deleted = kinesisCache.deleteKinesis('eu-west-1');
- To use the KMS cache to configure and cache an AWS KMS instance per region
const kmsCache = require('aws-core-utils/kms-cache');
const context = {};
const logging = require('logging-utils');
logging.configureLogging(context);
const kmsOptions = {
maxRetries: 0
};
const kms = kmsCache.setKMS(kmsOptions, context);
kmsCache.configureKMS(context, kmsOptions);
console.log(context.kms);
const kms1 = kmsCache.getKMS();
const kms2 = kmsCache.getKMS('us-west-2');
const optionsUsed1 = kmsCache.getKMSOptionsUsed();
const optionsUsed2 = kmsCache.getKMSOptionsUsed('us-west-1');
const deleted = kmsCache.deleteKMS('eu-west-1');
- To use the AWS.KMS utilities
const kmsUtils = require('aws-core-utils/kms-utils');
const kms = new AWS.KMS({region: 'eu-west-1'});
const logging = require('logging-utils');
const logger = logging.configureLogging({});
const accountId = 'XXXXXXXXXXXX';
const kmsKeyAlias = 'aws/lambda';
const keyId = `arn:aws:kms:us-west-2:${accountId}:alias/${kmsKeyAlias}`;
const plaintext = 'Shhhhhhhhhhhhhhh';
kmsUtils.encryptKey(kms, keyId, plaintext, logger)
.then(ciphertextBase64 => console.log(JSON.stringify(ciphertextBase64)));
const ciphertextBase64 = '...';
kmsUtils.decryptKey(kms, ciphertextBase64, logger)
.then(plaintext => console.log(JSON.stringify(plaintext)));
const encryptParams = {KeyId: keyId, Plaintext: plaintext};
kmsUtils.encrypt(kms, encryptParams, logger)
.then(result => console.log(JSON.stringify(result)));
const decryptParams = {CiphertextBlob: new Buffer(ciphertextBase64, 'base64')};
kmsUtils.decrypt(kms, decryptParams, logger)
.then(result => console.log(JSON.stringify(result)));
- To use the Lambda cache to configure and cache an AWS Lambda instance per region
const lambdaCache = require('aws-core-utils/lambda-cache');
const context = {};
const logging = require('logging-utils');
logging.configureLogging(context);
const lambdaOptions = {
maxRetries: 0
};
const lambda = lambdaCache.setLambda(lambdaOptions, context);
lambdaCache.configureLambda(context, lambdaOptions);
console.log(context.lambda);
const lambda1 = lambdaCache.getLambda();
const lambda2 = lambdaCache.getLambda('us-west-2');
const optionsUsed1 = lambdaCache.getLambdaOptionsUsed();
const optionsUsed2 = lambdaCache.getLambdaOptionsUsed('us-west-1');
const deleted = lambdaCache.deleteLambda('eu-west-1');
- To use the AWS.Lambda utilities
const lambdaUtils = require('aws-core-utils/lambda-utils');
const lambda = new AWS.Lambda({region: 'eu-west-1'});
const params = {FunctionName: 'my-lambda-function'};
lambdaUtils.listEventSourceMappings(lambda, params, context)
.then(result => console.log(JSON.stringify(result)));
const params2 = {FunctionName: 'my-lambda-function', UUID: uuid, BatchSize: 99};
lambdaUtils.updateEventSourceMapping(lambda, params2, context)
.then(result => console.log(JSON.stringify(result)));
lambdaUtils.disableEventSourceMapping(lambda, 'my-lambda-function', uuid, context)
.then(result => console.log(JSON.stringify(result)));
- To use the Lambda utilities
const lambdas = require('aws-core-utils/lambdas');
const alias = lambdas.getAlias(awsContext);
const functionName = lambdas.getFunctionName(awsContext);
const functionVersion = lambdas.getFunctionVersion(awsContext);
const functionNameVersionAndAlias = lambdas.getFunctionNameVersionAndAlias(awsContext);
const invokedFunctionArn = lambdas.getInvokedFunctionArn(awsContext);
const invokedFunctionArnFunctionName = lambdas.getInvokedFunctionArnFunctionName(awsContext);
lambdas.failCallback(lambdaCallback, error, awsContext, message, code);
- To get the current AWS region & configure it on a context
const regions = require('aws-core-utils/regions');
const region = regions.getRegion();
const context = {};
const failFast = true;
regions.configureRegion(context, failFast);
assert(context.region && typeof context.region === 'string');
- To use the stage utilities
const stages = require('aws-core-utils/stages');
const settings = undefined;
const options = require('aws-core-utils/stages-options.json');
stages.configureDefaultStageHandling(context);
const stageHandlingOptions = require('aws-core-utils/stages-options.json').stageHandlingOptions;
const otherSettings = undefined;
const otherOptions = require('aws-core-utils/test/sample-standard-options.json');
const forceConfiguration = false;
stages.configureDefaultStageHandling(context, stageHandlingOptions, otherSettings, otherOptions, forceConfiguration);
const stageHandlingSettings = stages.getDefaultStageHandlingSettings(options.stageHandlingOptions);
stages.configureStageHandling(context, stageHandlingSettings, stageHandlingOptions, otherSettings, otherOptions, forceConfiguration);
const stageHandlingSettings2 = {
envStageName: myEnvStageName,
customToStage: myCustomToStageFunction,
convertAliasToStage: myConvertAliasToStageFunction,
injectStageIntoStreamName: myInjectStageIntoStreamNameFunction,
extractStageFromStreamName: myExtractStageFromStreamNameFunction,
streamNameStageSeparator: myStreamNameStageSeparator,
injectStageIntoResourceName: myInjectStageIntoResourceNameFunction,
extractStageFromResourceName: myExtractStageFromResourceNameFunction,
resourceNameStageSeparator: myResourceNameStageSeparator,
injectInCase: myInjectInCase,
extractInCase: myExtractInCase,
defaultStage: myDefaultStage,
};
stages.configureStageHandling(context, stageHandlingSettings2, undefined, otherSettings, otherOptions, forceConfiguration);
stages.configureStageHandling(context, stageHandlingSettings, stageHandlingOptions, otherSettings, otherOptions, forceConfiguration);
const configured = stages.isStageHandlingConfigured(context);
const settingName = 'injectInCase';
const setting = stages.getStageHandlingSetting(context, settingName);
const functionSettingName = 'convertAliasToStage';
const fn = stages.getStageHandlingFunction(context, functionSettingName);
const context = {};
const stage = stages.resolveStage(awsEvent, awsContext, context);
const failFast = true;
stages.configureStage(context, awsEvent, awsContext, failFast);
assert(context.stage && typeof context.stage === 'string');
const qualifiedStreamName = 'TestStream_PROD';
const stage2 = stages.extractStageFromQualifiedStreamName(qualifiedStreamName, context);
assert(stage2 === 'prod');
const unqualifiedStreamName = 'TestStream';
const stageQualifiedStreamName = stages.toStageQualifiedStreamName(unqualifiedStreamName, stage2, context);
assert(stageQualifiedStreamName === 'TestStream_PROD');
const qualifiedTableName = 'TestTable_QA';
const stage3 = stages.extractStageFromQualifiedResourceName(qualifiedTableName, context);
assert(stage3 === 'qa');
const unqualifiedTableName = 'TestTable';
const stageQualifiedResourceName = stages.toStageQualifiedResourceName(unqualifiedTableName, stage3, context);
assert(stageQualifiedResourceName === 'TestTable_QA');
- To use the stream event utilities
const streamEvents = require('aws-core-utils/stream-events');
const eventSourceARNs = streamEvents.getEventSourceARNs(event);
const eventSourceStreamNames = streamEvents.getKinesisEventSourceStreamNames(event);
const eventSourceStreamName = streamEvents.getKinesisEventSourceStreamName(record);
const dynamoDBEventSourceTableName = streamEvents.getDynamoDBEventSourceTableName(record);
const tableNameAndStreamTimestamp = streamEvents.getDynamoDBEventSourceTableNameAndStreamTimestamp(record);
const dynamoDBEventSourceTableName1 = tableNameAndStreamTimestamp[0];
const dynamoDBEventSourceStreamTimestamp = tableNameAndStreamTimestamp[1];
try {
streamEvents.validateStreamEventRecord(record);
streamEvents.validateKinesisStreamEventRecord(record);
streamEvents.validateDynamoDBStreamEventRecord(record);
} catch (err) {
}
Unit tests
This module's unit tests were developed with and must be run with tape. The unit tests have been tested on Node.js v4.3.2.
Install tape globally if you want to run multiple tests at once:
$ npm install tape -g
Run all unit tests with:
$ npm test
or with tape:
$ tape test/*.js
See the package source for more details.
Changes
See release_notes.md