Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

aws-core-utils

Package Overview
Dependencies
Maintainers
1
Versions
80
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aws-core-utils - npm Package Compare versions

Comparing version 0.9.0 to 1.0.0

aws-errors.js

7

lambdas.js
'use strict';
/**
* Utilities for working with AWS Lambda - enables extraction of function names, versions and, most importantly, aliases
* from AWS contexts and their invoked function ARNs.
* @module aws-core-utils/lambdas.js
* @author Byron du Preez
*/
module.exports = {

@@ -4,0 +11,0 @@ getFunctionName: getFunctionName,

6

package.json
{
"name": "aws-core-utils",
"version": "0.9.0",
"version": "1.0.0",
"description": "Core utilities for working with Amazon Web Services (AWS), including arns, regions, stages, lambdas, etc.",

@@ -14,5 +14,5 @@ "author": "Byron du Preez",

"dependencies": {
"core-functions": "^1.1.0"
"core-functions": "^1.1.1"
},
"repository": "https://github.com/byron-dupreez/task-utils"
"repository": "https://github.com/byron-dupreez/aws-core-utils"
}

@@ -1,2 +0,2 @@

# aws-core-utils v0.9.0
# aws-core-utils v1.0.0

@@ -15,3 +15,6 @@ Core utilities for working with Amazon Web Services (AWS), including arns, regions, stages, etc.

- lambdas.js
- Utilities for working with AWS Lambdas.
- 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.
- aws-errors.js
- Utilities for working with AWS errors.

@@ -38,2 +41,8 @@ This module is exported as a [Node.js](https://nodejs.org/) module.

const stages = require('aws-core-utils/stages');
// To use the L from AWS events
const lambdas = require('aws-core-utils/lambdas');
// To use the AWS errors utilities
const awsErros = require('aws-core-utils/aws-errors');
```

@@ -59,1 +68,12 @@

See the [package source](https://github.com/byron-dupreez/aws-core-utils) for more details.
## Changes
### 0.9.0
- Initial commit
### 1.0.0
- Completed changes needed to release 1.0.0
- Added unit tests for stages.js
- Simplified regions.js API down to relevant methods
- Fixed defects attempting to source awsRegion and eventSourceARN from event instead of Kinesis records within event.
- Patched repository in package.json

@@ -9,13 +9,13 @@ 'use strict';

module.exports = {
getAwsRegion: getAwsRegion,
getAwsDefaultRegion: getAwsDefaultRegion,
getAwsRegionOrDefault: getAwsRegionOrDefault,
getRegion: getRegion,
getDefaultRegion: getDefaultRegion,
//getRegionOrDefault: getRegionOrDefault,
getInvokedFunctionArnRegion: getInvokedFunctionArnRegion,
getEventAwsRegion: getEventAwsRegion,
getEventSourceArnRegion: getEventSourceArnRegion,
resolveRegion: resolveRegion,
getEventAwsRegions: getEventAwsRegions,
getEventSourceArnRegions: getEventSourceArnRegions,
//resolveRegion: resolveRegion,
ONLY_FOR_TESTING: {
getAwsRegionRaw: getAwsRegionRaw,
getAwsDefaultRegionRaw: getAwsDefaultRegionRaw,
setAwsRegionIfNotSet: setAwsRegionIfNotSet
getRegionRaw: getRegionRaw,
getDefaultRegionRaw: getDefaultRegionRaw,
setRegionIfNotSet: setRegionIfNotSet
}

@@ -47,3 +47,3 @@ };

*/
function getAwsRegion() {
function getRegion() {
return trimOrEmpty(process.env.AWS_REGION);

@@ -56,3 +56,3 @@ }

*/
function getAwsDefaultRegion() {
function getDefaultRegion() {
return trimOrEmpty(process.env.AWS_DEFAULT_REGION);

@@ -62,13 +62,2 @@ }

/**
* Gets the region from the AWS_REGION environment variable if it exists; otherwise from the AWS_DEFAULT_REGION
* environment variable.
* @returns {string} the AWS region (if it exists); otherwise the AWS default region (if that exists; otherwise an empty
* string.
*/
function getAwsRegionOrDefault() {
const awsRegion = getAwsRegion();
return isNotBlank(awsRegion) ? awsRegion : getAwsDefaultRegion();
}
/**
* Sets the process.env.AWS_REGION environment variable to the given region, but ONLY if is is not already set!

@@ -78,3 +67,3 @@ * NB: This only sets the region temporarily on the current process and should probably only be used for testing purposes.

*/
function setAwsRegionIfNotSet(awsRegion) {
function setRegionIfNotSet(awsRegion) {
// Replaces an undefined or null awsRegion with '', otherwise it will become 'undefined' or 'null' on process.env

@@ -84,3 +73,3 @@ const newRegion = trimOrEmpty(awsRegion);

// Check if AWS region is already set or not
const region = getAwsRegion();
const region = getRegion();
if (isBlank(region)) {

@@ -111,78 +100,80 @@ // Attempt to set the AWS_REGION

/**
* Extracts the region from the given event's awsRegion property (if any); otherwise returns an empty string.
* Extracts the regions from the given event's record's awsRegion properties (if any); otherwise returns an empty array.
*
* Note that for this to work rhe given event should have an awsRegion property, which is the case for AWS Kinesis and
* DynamoDB stream events and for S3 Put and Delete events (and possibly for other AWS events as well).
* Note that for this to work rhe given event should have records with an awsRegion property, which is the case for AWS
* Kinesis and DynamoDB stream events and for S3 Put and Delete events (and possibly for other AWS events as well).
*
* @param event the event from which to extract the awsRegion
* @returns {string} the AWS region (if extracted) or an empty string
* @param event the event from which to extract its records' AWS regions
* @returns {string[]} the event's records' AWS regions (if any) or an empty array
*/
function getEventAwsRegion(event) {
return event && event.awsRegion ? trimOrEmpty(event.awsRegion) : '';
function getEventAwsRegions(event) {
return event && event.Records ?
event.Records.map(record => record.awsRegion ? trimOrEmpty(event.awsRegion) : '') : [];
}
/**
* Extracts the region from the given event's eventSourceARN property (if any); otherwise returns an empty string.
* Extracts the regions from the given event's record's eventSourceARN properties (if any); otherwise returns an empty
* array.
*
* Note that for this to work the given event should have an eventSourceARN property, which is the case for AWS Kinesis
* and DynamoDB stream events.
* Note that for this to work the given event should have records with an eventSourceARN property, which is the case for
* AWS Kinesis and DynamoDB stream events.
*
* @param event the event from which to access the eventSourceARN property
* @returns {string} the AWS region (if extracted) or an empty string
* @param event the event from which to extract its records' event source ARN regions
* @returns {string[]} the event's records' event source ARN regions (if any) or an empty array
*/
function getEventSourceArnRegion(event) {
return event && isNotBlank(event.eventSourceARN) ? getArnRegion(event.eventSourceARN) : '';
function getEventSourceArnRegions(event) {
return event && event.Records ?
event.Records.map(record => record.eventSourceARN ? getArnRegion(record.eventSourceARN) : '') : [];
}
/**
* Extracts a region from the following resources in the following order:
* 1. Using {@linkcode getAwsRegion}
* 2. awsContext.invokedFunctionArn
* 3. event.awsRegion
* 4. awsContext.eventSourceARN
*
* The detailed process followed is as follows:
* 1. Attempts to get the region using {@linkcode getAwsRegion} (i.e. from AWS-specific environment variables).
*
* 2. Extracts and returns the region from the given awsContext's invokedFunctionArn, if it contains an
* invokedFunctionArn in the form of "arn:aws:lambda:<region>:<accountId>:function:<functionName>[:functionAlias]".
* The ARN might be either a function ARN or an alias ARN (prefer the latter!). An unqualified ARN executes the
* $LATEST version (and cannot be used to extract an alias) and aliases execute the function version to which it they
* are pointing.
*
* 3. Returns the awsRegion from the given event's awsRegion, if it contains an awsRegion property.
*
* 4. Extracts and returns the region from the given event's eventSourceARN, if it contains an eventSourceARN
* in the form of "arn:aws:kinesis:<region>:<accountId>:stream/<streamName>".
*
* 5. Gives up and returns an empty string.
*
* @param {Object} event the Kinesis event to be checked
* @param {Object} awsContext the AWS context
* @return {string} the region if found; otherwise an empty string
*/
function resolveRegion(event, awsContext) {
// Attempt 1
let region = getAwsRegion();
if (isNotBlank(region)) {
return region;
}
// Attempt 2
region = getInvokedFunctionArnRegion(awsContext);
if (isNotBlank(region)) {
return region;
}
// Attempt 3
region = getEventAwsRegion(event);
if (isNotBlank(region)) {
return region;
}
// Attempt 4
region = getEventSourceArnRegion(event);
if (isNotBlank(region)) {
return region;
}
// Give up
return '';
}
// /**
// * Extracts a region from the following resources in the following order:
// * 1. Using {@linkcode getRegion}
// * 2. The region extracted from the given AWS context's invokedFunctionArn (if any)
// * 3. The first non-blank awsRegion (if any) extracted from the event's records
// * 4. The first non-blank eventSourceARN region (if any) extracted from the event's records
// *
// * The detailed process followed is as follows:
// * 1. Attempts to get the region using {@linkcode getRegion} (i.e. from AWS-specific environment variables).
// *
// * 2. Extracts and returns the region from the given awsContext's invokedFunctionArn, if it contains an
// * invokedFunctionArn in the form of "arn:aws:lambda:<region>:<accountId>:function:<functionName>[:functionAlias]".
// *
// * 3. Returns the first non-blank awsRegion (if any) extracted from the event's records, if any of them contain an awsRegion property.
// *
// * 4. Returns the first non-blank eventSourceARN region (if any) extracted from the event's records, if any of them contain an
// *
// * Extracts and returns the region from the given event's eventSourceARN, if it contains an eventSourceARN
// * in the form of "arn:aws:kinesis:<region>:<accountId>:stream/<streamName>".
// *
// * 5. Gives up and returns an empty string.
// *
// * @param {Object} event the Kinesis event to be checked
// * @param {Object} awsContext the AWS context
// * @return {string} the region if found; otherwise an empty string
// */
// function resolveRegion(event, awsContext) {
// // Attempt 1
// let region = getRegion();
// if (isNotBlank(region)) {
// return region;
// }
// // Attempt 2
// region = getInvokedFunctionArnRegion(awsContext);
// if (isNotBlank(region)) {
// return region;
// }
// // Attempt 3
// region = getEventAwsRegions(event).find(r => isNotBlank(r));
// if (isNotBlank(region)) {
// return region;
// }
// // Attempt 4
// region = getEventSourceArnRegions(event).find(r => isNotBlank(r));
// if (isNotBlank(region)) {
// return region;
// }
// // Give up
// return '';
// }

@@ -194,7 +185,7 @@

*
* Note: Added for testing, use {@linkcode getAwsRegion} instead, which also converts undefined and null to empty strings
* Note: Added for testing, use {@linkcode getRegion} instead, which also converts undefined and null to empty strings
*
* @returns {string|undefined|null} the AWS region (if it exists); otherwise an empty string, undefined or null.
*/
function getAwsRegionRaw() {
function getRegionRaw() {
return trim(process.env.AWS_REGION);

@@ -207,3 +198,3 @@ }

*
* Note: Added for testing, use {@linkcode getAwsDefaultRegion} instead, which also converts undefined and null to empty
* Note: Added for testing, use {@linkcode getDefaultRegion} instead, which also converts undefined and null to empty
* strings

@@ -213,5 +204,5 @@ *

*/
function getAwsDefaultRegionRaw() {
function getDefaultRegionRaw() {
return trim(process.env.AWS_DEFAULT_REGION);
}

@@ -10,12 +10,15 @@ 'use strict';

module.exports = {
isResolveStageConfigured: isResolveStageConfigured,
configureResolveStage: configureResolveStage,
configureResolveStageWithDefaults: configureResolveStageWithDefaults,
resolveStage: resolveStage,
resolveRawStage: resolveRawStage,
resolveStageUsingDefaultFunctions: resolveStageUsingDefaultFunctions,
getResolveStageSetting: getResolveStageSetting,
appendStage: appendStage,
convertAliasToStage: convertAliasToStage,
convertStreamNameSuffixToStage: convertStreamNameSuffixToStage
convertStreamNameSuffixToStage: convertStreamNameSuffixToStage,
FOR_TESTING_ONLY: {
toCase: toCase
}
};
const config = require('./config');
const Strings = require('core-functions/strings');

@@ -36,60 +39,126 @@ const trim = Strings.trim;

const DEFAULT_STREAM_NAME_STAGE_SEPARATOR = '_';
const DEFAULT_IN_CASE = 'lowercase';
/**
* Attempts to resolve the raw stage (see {@linkcode resolveRawStage}) and then converts the resolved raw stage into
* lowercase or uppercase (if context.useUpperCaseForStages is true).
* Returns true if resolve stage settings are already configured on the given context; false otherwise.
* @param context the context to check
* @returns {boolean} true if configured; false otherwise
*/
function isResolveStageConfigured(context) {
return context && typeof context.resolveStageConfig === 'object';
}
/**
* Configures the given context with the given resolve stage settings, but only if there are no resolve stage settings
* already configured on the given context OR if forceConfiguration is true. The resolve stage settings determine how
* {@linkcode resolveStage} will behave when invoked.
*
* @param {Object} event - the AWS event
* @param {Object} awsContext - the AWS context, which was passed to your lambda
* @param {Function|undefined} convertAliasToStage - an optional function that accepts: the extracted alias (if any); the
* AWS event; the AWS context; and the context, and converts the alias into a stage or returns an empty string
* @param {Function|undefined} convertStreamNameToStage - an optional function that accepts: the stream name; the AWS
* event; the AWS context; and the context, and extracts a stage from the stream name or returns an empty string
* @param {Object} context - the context, which can be used to pass additional configuration through to the given functions
* @param {string|undefined} [context.stage] - an optional stage on the given context
* @param {string|undefined} [context.defaultStage] - an optional default stage on the given context
* @param {boolean|undefined} [context.useUpperCaseForStages] - an optional flag on the given context, which if present
* indicates whether to convert the resolved stage to uppercase rather than to lowercase
* @returns {string} the resolved stage (if non-blank) in lowercase or uppercase; otherwise an empty string
* @param {Object} context the context onto which to configure resolve stage settings
* @param {Function|undefined} convertAliasToStage - an optional function that accepts: an extracted alias (if any);
* an AWS event; an AWS context; and a context, and converts the alias into a stage or returns an empty string
* @param {Function|undefined} convertStreamNameToStage - an optional function that accepts: a stream name; an AWS
* event; an AWS context; and a context, and extracts a stage from the stream name or returns an empty string
* @param {string|undefined} streamNameStageSeparator - an optional non-blank separator to use instead of '_' to
* extract a stage from a stream name
* @param {string|undefined} defaultStage - an optional default stage to use as a last resort if all other attempts fail
* @param {string|undefined} inCase - specifies whether to convert a resolved stage to uppercase (if 'uppercase' or
* 'upper') or to lowercase (if 'lowercase' or 'lower') or keep it as resolved (if anything else)
* @param {boolean|undefined} forceConfiguration whether or not to force configuration of the given settings, which will
* override any previously configured resolve stage settings on the given context
* @return {Object} the updated context object
*/
function resolveStage(event, awsContext, convertAliasToStage, convertStreamNameToStage, context) {
// Resolve the raw stage
const stage = resolveRawStage(event, awsContext, convertAliasToStage, convertStreamNameToStage, context);
function configureResolveStage(context, convertAliasToStage, convertStreamNameToStage, streamNameStageSeparator,
defaultStage, inCase, forceConfiguration) {
// Convert the raw stage (if any) to lowercase or uppercase (if context.useUpperCaseForStages is true)
return toLowerOrUpperCase(trimOrEmpty(stage), context && context.useUpperCaseForStages);
// If forceConfiguration is false check if the given context already has stage resolution configured on it
// and, if so, do nothing more and simply return the context as is (to prevent overriding an earlier configuration)
if (!forceConfiguration && isResolveStageConfigured(context)) {
return context;
}
// Configure the resolve stage settings
context.resolveStageConfig = {
convertAliasToStage: convertAliasToStage,
convertStreamNameToStage: convertStreamNameToStage,
streamNameStageSeparator: streamNameStageSeparator,
defaultStage: defaultStage,
inCase: inCase
};
return context;
}
/**
* Attempts to resolve the raw stage from the following resources in the following order:
* Configures the given context with the default resolve stage settings, but only if there are no resolve stage settings
* already configured on the given context OR if forceConfiguration is true. The resolve stage settings determine how
* {@linkcode resolveStage} will behave when invoked.
*
* @param {Object} context the context onto which to configure resolve stage settings
* @param {boolean|undefined} forceConfiguration whether or not to force configuration of the given settings, which will
* override any previously configured resolve stage settings on the given context
* @return {Object} the updated context object
*/
function configureResolveStageWithDefaults(context, forceConfiguration) {
return configureResolveStage(context, convertAliasToStage, convertStreamNameSuffixToStage,
DEFAULT_STREAM_NAME_STAGE_SEPARATOR, undefined, DEFAULT_IN_CASE, forceConfiguration);
}
/**
* Attempts to resolve the stage from the given AWS event, AWS context and context using the following process:
* 1. Uses context.stage (if non-blank).
*
* 2. Uses the AWS event's stage (if non-blank).
* NB: event.stage is NOT a standard AWS event property, but it may be set by API Gateway or tools like serverless.
* TODO check whether API Gateway sets the stage on the event and if so confirm WHERE it sets it!
*
* 3. Extracts the alias from the AWS context's invokedFunctionArn (if any) and then uses the given convertAliasToStage
* function (if provided) to convert the extracted alias (if any) into a stage.
* 3. Extracts the alias from the AWS context's invokedFunctionArn (if any) and then uses the given context's
* resolveStageConfig.convertAliasToStage function (if any) to convert the extracted alias (if any) into a stage.
*
* 4. Extracts the stream name from the AWS event's eventSourceARN (if any) and then uses the given convertStreamNameToStage
* function (if provided) to convert the extracted stream name (if any) into a stage.
* NB: This step relies on a convention of using stages as Lambda aliases and, hence, should be skipped, if you
* are NOT using such a convention, by simply NOT configuring a resolveStageConfig.convertAliasToStage function
* on the given context.
*
* 4. Extracts the stream names from the AWS event's records' eventSourceARNs (if any) and then uses the given context's
* resolveStageConfig.convertStreamNameToStage function (if any) to convert the extracted stream names into stages
* and returns the first non-blank stage (if any).
*
* NB: This step relies on a convention of qualifying stream names with a stage and, hence, should be skipped, if you
* are NOT using such a convention, by simply NOT providing a convertStreamNameToStage function.
* are NOT using such a convention, by simply NOT configuring a resolveStageConfig.convertStreamNameToStage function
* on the given context.
*
* 5. Uses context.defaultStage (if non-blank).
* 5. Uses context.resolveStageConfig.defaultStage (if non-blank).
*
* 6. Gives up and returns an empty string.
*
* NB: If no resolve stage settings have been configured by the time this function is first called, then the given
* context will be configured with the default resolve stage settings (see {@linkcode configureResolveStageWithDefaults}).
*
* @param {Object} event - the AWS event
* @param {Object} awsContext - the AWS context, which was passed to your lambda
* @param {Function|undefined} convertAliasToStage - an optional function that accepts: the extracted alias (if any); the
* AWS event; the AWS context; and the context, and converts the alias into a stage or returns an empty string
* @param {Function|undefined} convertStreamNameToStage - an optional function that accepts: the stream name; the AWS
* event; the AWS context; and the context, and extracts a stage from the stream name or returns an empty string
* @param {Object} context - the context, which can be used to pass additional configuration through to the given functions
* @param {string|undefined} [context.stage] - an optional stage on the given context
* @param {string|undefined} [context.defaultStage] - an optional default stage on the given context
* @returns {string} the resolved raw stage (if non-blank); otherwise an empty string
* @param {Object} context - the context, which can also be used to pass additional configuration through to any custom
* convertAliasToStage or convertStreamNameToStage functions that you configured
* @param {string|undefined} [context.stage] - an optional stage on the given context, which will short-circuit
* resolution to this stage (if non-blank)
* @param {Function|undefined} [context.resolveStageConfig.convertAliasToStage] - an optional function on the given
* context that accepts: an extracted alias (if any); an AWS event; an AWS context; and a context, and converts the
* alias into a stage or returns an empty string
* @param {Function|undefined} [context.resolveStageConfig.convertStreamNameToStage] - an optional function on the given
* context that accepts: a Kinesis stream name; an AWS event; an AWS context; and a context, and extracts a stage from
* the stream name or returns an empty string
* @param {string|undefined} [context.resolveStageConfig.defaultStage] - an optional default stage on the given context
* to use as a last resort if all other attempts fail
* @param {string|undefined} [context.resolveStageConfig.inCase] - specifies whether to convert the resolved stage to
* uppercase (if 'uppercase' or 'upper') or to lowercase (if 'lowercase' or 'lower') or keep it as resolved (if anything else)
* @returns {string} the resolved stage (if non-blank); otherwise an empty string
*/
function resolveRawStage(event, awsContext, convertAliasToStage, convertStreamNameToStage, context) {
function resolveStage(event, awsContext, context) {
// If no resolve stage settings have been configured yet, then configure the given context with the default settings
if (!isResolveStageConfigured(context)) {
configureResolveStageWithDefaults(context, true);
}
const inCase = getResolveStageSetting(context, 'inCase');
// Attempt 1
if (context && isNotBlank(context.stage)) {
return context.stage;
return toCase(trim(context.stage), inCase);
}

@@ -99,3 +168,3 @@

if (event && isNotBlank(event.stage)) {
return event.stage;
return toCase(trim(event.stage), inCase);
}

@@ -105,2 +174,4 @@

// Check have all the pieces needed to extract an alias and apply the given convertAliasToStage function to it
const convertAliasToStage = getResolveStageSetting(context, 'convertAliasToStage');
if (awsContext && isNotBlank(awsContext.functionVersion) && isNotBlank(awsContext.invokedFunctionArn) &&

@@ -114,3 +185,3 @@ isFunction(convertAliasToStage)) {

if (isNotBlank(stage)) {
return stage;
return toCase(trim(stage), inCase);
}

@@ -120,11 +191,20 @@ }

// Attempt 4
function extractStageFromEventSourceARN(record) {
if (record && isNotBlank(record.eventSourceARN)) {
// Extract the stream name
const streamName = getArnResources(record.eventSourceARN).resource;
// If the stream name is not blank, apply the convertStreamNameToStage function to it to derive a stage
return isNotBlank(streamName) ? convertStreamNameToStage(streamName, event, awsContext, context) : '';
}
return '';
}
// Check have all the pieces needed to extract a stream name and apply the given convertStreamNameToStage function to it
if (event && isNotBlank(event.eventSourceARN) && isFunction(convertStreamNameToStage)) {
// Extract the stream name
const streamName = getArnResources(event.eventSourceARN).resource;
const convertStreamNameToStage = getResolveStageSetting(context, 'convertStreamNameToStage');
// If the stream name is not blank, apply the convertStreamNameToStage function to it to derive a stage
const stage = isNotBlank(streamName) ? convertStreamNameToStage(streamName, event, awsContext, context) : '';
if (event && event.Records && event.Records.length > 0 && isFunction(convertStreamNameToStage)) {
const stage = event.Records.map(extractStageFromEventSourceARN).find(s => isNotBlank(s));
if (isNotBlank(stage)) {
return stage;
return toCase(trim(stage), inCase);
}

@@ -134,4 +214,5 @@ }

// Attempt 5
if (context && isNotBlank(context.defaultStage)) {
return context.defaultStage;
const defaultStage = getResolveStageSetting(context, 'defaultStage');
if (isNotBlank(defaultStage)) {
return toCase(trim(defaultStage), inCase);
}

@@ -144,11 +225,10 @@

/**
* A short-cut to resolving the stage, which uses the default {@linkcode convertAliasToStage} and
* {@linkcode convertStreamNameSuffixToStage} functions.
* @param {Object} event - the AWS event
* @param {Object} awsContext - the AWS context
* @param {Object} context - the context
* @returns {string} the resolved stage (if non-blank); otherwise an empty string
* Returns the value of the named resolve stage setting (if any) on the given context.
* @param context the context from which to fetch the named setting's value
* @param settingName the name of the resolve stage setting
* @returns {*|undefined} the value of the named setting (if any); otherwise undefined
*/
function resolveStageUsingDefaultFunctions(event, awsContext, context) {
return resolveStage(event, awsContext, convertAliasToStage, convertStreamNameSuffixToStage, context);
function getResolveStageSetting(context, settingName) {
return context && context.resolveStageConfig && isNotBlank(settingName) && context.resolveStageConfig[settingName] ?
context.resolveStageConfig[settingName] : undefined;
}

@@ -171,3 +251,3 @@

* stream name. The suffix is extracted from the given stream name by taking everything after the last occurrence of
* the context.streamNameStageSeparator (if any) or the default ('_') separator.
* the configured streamNameStageSeparator (if any) or the default separator ('_').
* @param {string} streamName the name of the source stream (originally extracted from the AWS event's eventSourceArn)

@@ -177,3 +257,4 @@ * @param {Object} event the AWS event

* @param {Object} context the context
* @param {string|undefined} [context.streamNameStageSeparator] - an optional separator to use instead of '_'
* @param {string|undefined} [context.resolveStageConfig.streamNameStageSeparator] - an optional non-blank separator to
* use instead of '_'
* @returns {string} the stage or an empty string

@@ -183,3 +264,4 @@ */

if (isNotBlank(streamName)) {
const separator = context && context.streamNameStageSeparator ? context.streamNameStageSeparator : '_';
const separatorSetting = getResolveStageSetting(context, 'streamNameStageSeparator');
const separator = isNotBlank(separatorSetting) ? separatorSetting : '_';
const suffixStartPos = streamName.lastIndexOf(separator);

@@ -192,12 +274,2 @@ return suffixStartPos !== -1 ? trimOrEmpty(streamName.substring(suffixStartPos + 1)) : '';

/**
* Converts the given string to uppercase, if toUpper is true; otherwise to lowercase.
* @param {string} s - the string to convert
* @param {boolean|*} toUpper - if true, convert to uppercase; otherwise to lowercase
* @returns {string} the upper or lowercase version of the string
*/
function toLowerOrUpperCase(s, toUpper) {
return s ? toUpper === true ? s.toUpperCase() : s.toLowerCase() : '';
}
/**
* Returns a stage-qualified version of the given base resource name with an appended "stage" suffix, which will contain

@@ -216,13 +288,23 @@ * the given separator followed by the given stage, which will be appended in uppercase, lowercase or as is according to

function appendStage(resourceName, separator, stage, inCase) {
if (isNotBlank(stage)) {
// Convert the given inCase argument to lowercase to facilitate matching
const inCaseToUse = trimOrEmpty(inCase && inCase.toLowerCase ? inCase.toLowerCase() : inCase);
return isNotBlank(stage) ? `${resourceName}${trimOrEmpty(separator)}${toCase(trim(stage), inCase)}` : resourceName;
}
/**
* Converts the given value to uppercase, lowercase or keeps it as is according to the given asCase argument.
* @param value the value to convert or keep as is
* @param {string} asCase - specifies whether to convert the value to uppercase (if 'uppercase' or 'upper') or to
* lowercase (if 'lowercase' or 'lower') or to keep it as provided (if anything else)
* @return {string} the converted or given value
*/
function toCase(value, asCase) {
if (isNotBlank(value)) {
// Convert the given asCase argument to lowercase to facilitate matching
const caseToUse = trimOrEmpty(asCase && asCase.toLowerCase ? asCase.toLowerCase() : asCase);
// Convert the given stage into the requested case
const stageInRightCase = trim(inCaseToUse === 'lowercase' || inCaseToUse === 'lower' ? stage.toLowerCase() :
inCaseToUse === 'uppercase' || inCaseToUse === 'upper' ? stage.toUpperCase() : stage);
return`${resourceName}${trimOrEmpty(separator)}${stageInRightCase}`;
return caseToUse === 'lowercase' || caseToUse === 'lower' ? value.toLowerCase() :
caseToUse === 'uppercase' || caseToUse === 'upper' ? value.toUpperCase() : value;
}
return resourceName;
return value;
}

@@ -18,13 +18,13 @@ 'use strict';

const getAlias = lambdas.getAlias;
const getInvokedFunctionArn = lambdas.getInvokedFunctionArn;
//const getInvokedFunctionArn = lambdas.getInvokedFunctionArn;
const getInvokedFunctionArnFunctionName = lambdas.getInvokedFunctionArnFunctionName;
const Strings = require('core-functions/strings');
const isBlank = Strings.isBlank;
const isNotBlank = Strings.isNotBlank;
const trim = Strings.trim;
const trimOrEmpty = Strings.trimOrEmpty;
// const Strings = require('core-functions/strings');
// const isBlank = Strings.isBlank;
// const isNotBlank = Strings.isNotBlank;
// const trim = Strings.trim;
// const trimOrEmpty = Strings.trimOrEmpty;
const samples = require('./samples');
const sampleInvokedFunctionArn = samples.sampleInvokedFunctionArn;
//const sampleInvokedFunctionArn = samples.sampleInvokedFunctionArn;
const sampleAwsContext = samples.sampleAwsContext;

@@ -31,0 +31,0 @@

{
"name": "aws-core-utils-tests",
"description": "Unit tests for aws-core-utils modules",
"version": "0.9.0",
"version": "1.0.0",
"author": "Byron du Preez",

@@ -6,0 +6,0 @@ "license": "Apache-2.0",

@@ -14,35 +14,27 @@ 'use strict';

const regions = require('../regions');
const getAwsRegion = regions.getAwsRegion;
const getAwsRegionRaw = regions.ONLY_FOR_TESTING.getAwsRegionRaw;
// const getAwsDefaultRegion = regions.getAwsDefaultRegion;
const getRegion = regions.getRegion;
const getRegionRaw = regions.ONLY_FOR_TESTING.getRegionRaw;
// const getDefaultRegion = regions.getDefaultRegion;
// const resolveRegion = regions.resolveRegion;
const setAwsRegionIfNotSet = regions.ONLY_FOR_TESTING.setAwsRegionIfNotSet;
const setRegionIfNotSet = regions.ONLY_FOR_TESTING.setRegionIfNotSet;
const Strings = require('core-functions/strings');
const isBlank = Strings.isBlank;
const isNotBlank = Strings.isNotBlank;
const trim = Strings.trim;
const trimOrEmpty = Strings.trimOrEmpty;
// const isNotBlank = Strings.isNotBlank;
// const trim = Strings.trim;
// const trimOrEmpty = Strings.trimOrEmpty;
const INVOKED_FUNCTION_ARN_REGION = 'INVOKED_FUNCTION_ARN_REGION';
const EVENT_AWS_REGION = 'EVENT_AWS_REGION';
const EVENT_SOURCE_ARN_REGION = 'EVENT_SOURCE_ARN_REGION';
// function sampleRegion(region) {
// return region ? region : defaultAwsRegion;
// }
// =====================================================================================================================
// Tests for getAwsRegion
// Tests for getRegion
// =====================================================================================================================
test('getAwsRegion and setAwsRegionIfNotSet', t => {
test('getRegion and setRegionIfNotSet', t => {
// Attempt to preserve the original AWS_REGION setting (unfortunately cannot preserve undefined or null)
const origAwsRegion = getAwsRegionRaw();
const origRegion = getRegionRaw();
// check orig
if (isBlank(origAwsRegion)) {
t.equal(origAwsRegion, process.env.AWS_REGION, `original raw must be '${process.env.AWS_REGION}'`);
t.equal(getAwsRegion(), '', `original must be empty string '${process.env.AWS_REGION}'`);
if (isBlank(origRegion)) {
t.equal(origRegion, process.env.AWS_REGION, `original raw must be '${process.env.AWS_REGION}'`);
t.equal(getRegion(), '', `original must be empty string '${process.env.AWS_REGION}'`);
}

@@ -57,27 +49,27 @@

process.env.AWS_REGION = unset;
console.log(`AFTER reset process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origAwsRegion})`);
console.log(`AFTER reset process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origRegion})`);
t.equal(process.env.AWS_REGION, unset, `process.env.AWS_REGION must be '${unset}' after reset`);
// check get when not set
t.equal(getAwsRegion(), unset, `must be '${unset}'`);
t.equal(getRegion(), unset, `must be '${unset}'`);
// check will set, when not set
const expected = 'TEST_REGION_1';
t.ok(setAwsRegionIfNotSet(expected), `must set successfully`);
t.equal(getAwsRegion(), expected, `must be ${expected}`);
t.ok(setRegionIfNotSet(expected), `must set successfully`);
t.equal(getRegion(), expected, `must be ${expected}`);
// check was NOT set, when already set set
t.notOk(setAwsRegionIfNotSet('TEST_REGION_3'), `must NOT set successfully`);
t.equal(getAwsRegion(), expected, `must still be ${expected}`);
t.notOk(setRegionIfNotSet('TEST_REGION_3'), `must NOT set successfully`);
t.equal(getRegion(), expected, `must still be ${expected}`);
} finally {
// "Restore" original aws region
console.log(`BEFORE restore process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origAwsRegion})`);
process.env.AWS_REGION = isBlank(origAwsRegion) ? unset : origAwsRegion;
console.log(`AFTER restore process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origAwsRegion})`);
console.log(`BEFORE restore process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origRegion})`);
process.env.AWS_REGION = isBlank(origRegion) ? unset : origRegion;
console.log(`AFTER restore process.env.AWS_REGION = '${process.env.AWS_REGION}' (orig was ${origRegion})`);
// Check "restore" worked
if (isBlank(origAwsRegion)) {
t.equal(getAwsRegion(), unset, `must be "restored" to '${unset}' (orig was ${origAwsRegion})`);
if (isBlank(origRegion)) {
t.equal(getRegion(), unset, `must be "restored" to '${unset}' (orig was ${origRegion})`);
} else {
t.equal(getAwsRegion(), origAwsRegion, `must be restored to ${origAwsRegion}`);
t.equal(getRegion(), origRegion, `must be restored to ${origRegion}`);
}

@@ -98,5 +90,5 @@ t.end();

// // Configure different regions to each of the 3 sources
// // const eventSourceArnRegion = EVENT_SOURCE_ARN_REGION;
// // const eventAwsRegion = EVENT_AWS_REGION;
// // const invokedFunctionArnRegion = INVOKED_FUNCTION_ARN_REGION;
// // const eventSourceArnRegion = 'ES_ARN_REGION';
// // const eventAwsRegion = 'EVENT_AWS_REGION';
// // const invokedFunctionArnRegion = 'IF_ARN_REGION';
//

@@ -103,0 +95,0 @@ // const eventSourceArn = sampleEventSourceArn(streamName); //, eventSourceArnRegion);

@@ -16,6 +16,2 @@ 'use strict';

const INVOKED_FUNCTION_ARN_REGION = 'INVOKED_FUNCTION_ARN_REGION';
const EVENT_AWS_REGION = 'EVENT_AWS_REGION';
const EVENT_SOURCE_ARN_REGION = 'EVENT_SOURCE_ARN_REGION';
const sampleMessage = {

@@ -34,6 +30,2 @@ key1: 'value1',

INVOKED_FUNCTION_ARN_REGION: INVOKED_FUNCTION_ARN_REGION,
EVENT_AWS_REGION: EVENT_AWS_REGION,
EVENT_SOURCE_ARN_REGION: EVENT_SOURCE_ARN_REGION,
// General

@@ -84,3 +76,3 @@ sampleNumberString: sampleNumberString,

function sampleInvokedFunctionArn(invokedFunctionArnRegion, functionName, functionAlias) {
const region = isNotBlank(invokedFunctionArnRegion) ? invokedFunctionArnRegion : INVOKED_FUNCTION_ARN_REGION;
const region = isNotBlank(invokedFunctionArnRegion) ? invokedFunctionArnRegion : 'IF_ARN_REGION';
const funcName = isNotBlank(functionName) ? functionName : sampleFunctionName;

@@ -92,3 +84,3 @@ const aliasSuffix = isNotBlank(functionAlias) ? `:${functionAlias}` : '';

function sampleEventSourceArn(eventSourceArnRegion, streamName) {
const region = isNotBlank(eventSourceArnRegion) ? eventSourceArnRegion : EVENT_SOURCE_ARN_REGION;
const region = isNotBlank(eventSourceArnRegion) ? eventSourceArnRegion : 'EF_ARN_REGION';
const streamName1 = isNotBlank(streamName) ? streamName : sampleStreamName();

@@ -130,3 +122,3 @@ return `arn:aws:kinesis:${region}:${sampleAwsAccountId}:stream/${streamName1}`;

const sequenceNumber = sampleNumberString(56);
const awsRegion = eventAwsRegion ? eventAwsRegion : EVENT_AWS_REGION;
const awsRegion = eventAwsRegion ? eventAwsRegion : 'EVENT_AWS_REGION';
return {

@@ -133,0 +125,0 @@ eventID: `shardId-000000000000:${shardId}`,

@@ -12,9 +12,514 @@ 'use strict';

const stages = require('../stages');
const isResolveStageConfigured = stages.isResolveStageConfigured;
const configureResolveStage = stages.configureResolveStage;
const configureResolveStageWithDefaults = stages.configureResolveStageWithDefaults;
const resolveStage = stages.resolveStage;
const resolveRawStage = stages.resolveRawStage;
const resolveStageUsingDefaultFunctions = stages.resolveStageUsingDefaultFunctions;
const getResolveStageSetting = stages.getResolveStageSetting;
const convertAliasToStage = stages.convertAliasToStage;
const convertStreamNameSuffixToStage = stages.convertStreamNameSuffixToStage;
const appendStage = stages.appendStage;
//const appendStage = stages.appendStage;
const toCase = stages.FOR_TESTING_ONLY.toCase;
//TODO add unit test for stages
const Strings = require('core-functions/strings');
const trim = Strings.trim;
const trimOrEmpty = Strings.trimOrEmpty;
//const isBlank = Strings.isBlank;
const isNotBlank = Strings.isNotBlank;
const stringify = Strings.stringify;
const samples = require('./samples');
// Constants
const latestFunctionVersion = samples.latestFunctionVersion;
// General
const sampleNumberString = samples.sampleNumberString;
// For AWS contexts
const sampleInvokedFunctionArn = samples.sampleInvokedFunctionArn;
const sampleAwsContext = samples.sampleAwsContext;
// For Kinesis events
const sampleStreamName = samples.sampleStreamName;
const sampleEventSourceArn = samples.sampleEventSourceArn;
const sampleEventSourceArnFromPrefixSuffix = samples.sampleEventSourceArnFromPrefixSuffix;
const sampleBase64Data = samples.sampleBase64Data;
const sampleKinesisEventWithSampleRecord = samples.sampleKinesisEventWithSampleRecord;
const sampleKinesisEventWithRecord = samples.sampleKinesisEventWithRecord;
const sampleKinesisEventWithRecords = samples.sampleKinesisEventWithRecords;
function checkConvertAliasToStage(alias, expected, t) {
t.equal(convertAliasToStage(alias, undefined, undefined, undefined), expected, `'${alias}' must be '${expected}'`);
}
function checkConvertStreamNameSuffixToStage(streamName, context, expected, t) {
t.equal(convertStreamNameSuffixToStage(streamName, undefined, undefined, context), expected
, `'${streamName}' must be '${expected}'`);
}
function checkResolveStage(eventStage, functionVersion, functionAlias, streamName, context, expected, t) {
// Create an AWS context
const invokedFunctionArn = sampleInvokedFunctionArn('invokedFunctionArnRegion', 'functionName', functionAlias);
const awsContext = sampleAwsContext('functionName', functionVersion, invokedFunctionArn);
// Create a Kinesis event
const eventSourceArn = sampleEventSourceArn('eventSourceArnRegion', streamName);
const event = sampleKinesisEventWithSampleRecord(undefined, undefined, eventSourceArn, 'eventAwsRegion');
if (isNotBlank(eventStage)) {
event.stage = eventStage;
}
// Resolve the stage
const actual = resolveStage(event, awsContext, context);
t.equal(actual, expected, `resolve: alias(${functionAlias}) stream(${streamName}) context(${context.stage}, ${context.defaultStage}) -> '${actual}' must be '${expected}'`);
}
function checkConfigureResolveStage(context, convertAliasToStage, convertStreamNameToStage, streamNameStageSeparator,
defaultStage, inCase, forceConfiguration, t) {
const before = context.resolveStageConfig;
const convertAliasToStageBefore = before ? before.convertAliasToStage : undefined;
const convertStreamNameToStageBefore = before ? before.convertStreamNameToStage : undefined;
const streamNameStageSeparatorBefore = before ? before.streamNameStageSeparator : undefined;
const defaultStageBefore = before ? before.defaultStage : undefined;
const inCaseBefore = before ? before.inCase : undefined;
const mustChange = forceConfiguration || !before;
// Configure it
configureResolveStage(context, convertAliasToStage, convertStreamNameToStage, streamNameStageSeparator, defaultStage,
inCase, forceConfiguration, t);
const after = context.resolveStageConfig;
const convertAliasToStageAfter = after ? after.convertAliasToStage : undefined;
const convertStreamNameToStageAfter = after ? after.convertStreamNameToStage : undefined;
const streamNameStageSeparatorAfter = after ? after.streamNameStageSeparator : undefined;
const defaultStageAfter = after ? after.defaultStage : undefined;
const inCaseAfter = after ? after.inCase : undefined;
t.ok(isResolveStageConfigured(context), `resolve stage settings must be configured now`);
// Set up the right expectations
const convertAliasToStageExpected = mustChange ? convertAliasToStage : convertAliasToStageBefore;
const convertStreamNameToStageExpected = mustChange ? convertStreamNameToStage : convertStreamNameToStageBefore;
const streamNameStageSeparatorExpected = mustChange ? streamNameStageSeparator : streamNameStageSeparatorBefore;
const defaultStageExpected = mustChange ? defaultStage : defaultStageBefore;
const inCaseExpected = mustChange ? inCase : inCaseBefore;
t.deepEqual(getResolveStageSetting(context, 'convertAliasToStage'), convertAliasToStageExpected, `convertAliasToStage (${stringify(convertAliasToStageAfter)}) must be ${stringify(convertAliasToStageExpected)}`);
t.deepEqual(getResolveStageSetting(context, 'convertStreamNameToStage'), convertStreamNameToStageExpected, `convertStreamNameToStage (${stringify(convertStreamNameToStageAfter)}) must be ${stringify(convertStreamNameToStageExpected)}`);
t.equal(getResolveStageSetting(context, 'streamNameStageSeparator'), streamNameStageSeparatorExpected, `streamNameStageSeparator (${stringify(streamNameStageSeparatorAfter)}) must be ${stringify(streamNameStageSeparatorExpected)}`);
t.equal(getResolveStageSetting(context, 'defaultStage'), defaultStageExpected, `defaultStage (${stringify(defaultStageAfter)}) must be ${stringify(defaultStageExpected)}`);
t.equal(getResolveStageSetting(context, 'inCase'), inCaseExpected, `inCase (${stringify(inCaseAfter)}) must be ${stringify(inCaseExpected)}`);
// Check whether resolve stage works with this configuration
const expected = mustChange ? toCase(trimOrEmpty(defaultStageExpected), inCaseExpected) : toCase(trimOrEmpty(defaultStageBefore), inCaseBefore);
checkResolveStage('', '', '', '', context, expected, t);
}
function checkConfigureResolveStageWithDefaults(context, forceConfiguration, t) {
const before = context.resolveStageConfig;
const convertAliasToStageBefore = before ? before.convertAliasToStage : undefined;
const convertStreamNameToStageBefore = before ? before.convertStreamNameToStage : undefined;
const streamNameStageSeparatorBefore = before ? before.streamNameStageSeparator : undefined;
const defaultStageBefore = before ? before.defaultStage : undefined;
const inCaseBefore = before ? before.inCase : undefined;
const mustChange = forceConfiguration || !before;
// Configure it
configureResolveStageWithDefaults(context, forceConfiguration, t);
const after = context.resolveStageConfig;
const convertAliasToStageAfter = after ? after.convertAliasToStage : undefined;
const convertStreamNameToStageAfter = after ? after.convertStreamNameToStage : undefined;
const streamNameStageSeparatorAfter = after ? after.streamNameStageSeparator : undefined;
const defaultStageAfter = after ? after.defaultStage : undefined;
const inCaseAfter = after ? after.inCase : undefined;
t.ok(isResolveStageConfigured(context), `resolve stage settings must be configured now`);
// Expect the defaults to be in place
const convertAliasToStageExpected = mustChange ? convertAliasToStage : convertAliasToStageBefore;
const convertStreamNameToStageExpected = mustChange ? convertStreamNameSuffixToStage : convertStreamNameToStageBefore;
const streamNameStageSeparatorExpected = mustChange ? '_' : streamNameStageSeparatorBefore;
const defaultStageExpected = mustChange ? undefined : defaultStageBefore;
const inCaseExpected = mustChange ? 'lowercase' : inCaseBefore;
t.deepEqual(getResolveStageSetting(context, 'convertAliasToStage'), convertAliasToStageExpected, `convertAliasToStage (${stringify(convertAliasToStageAfter)}) must be ${stringify(convertAliasToStageExpected)}`);
t.deepEqual(getResolveStageSetting(context, 'convertStreamNameToStage'), convertStreamNameToStageExpected, `convertStreamNameToStage (${stringify(convertStreamNameToStageAfter)}) must be ${stringify(convertStreamNameToStageExpected)}`);
t.equal(getResolveStageSetting(context, 'streamNameStageSeparator'), streamNameStageSeparatorExpected, `streamNameStageSeparator (${stringify(streamNameStageSeparatorAfter)}) must be ${stringify(streamNameStageSeparatorExpected)}`);
t.equal(getResolveStageSetting(context, 'defaultStage'), defaultStageExpected, `defaultStage (${stringify(defaultStageAfter)}) must be ${stringify(defaultStageExpected)}`);
t.equal(getResolveStageSetting(context, 'inCase'), inCaseExpected, `inCase (${stringify(inCaseAfter)}) must be ${stringify(inCaseExpected)}`);
// Check whether resolve stage works with this configuration
const expected = toCase(trimOrEmpty(defaultStageExpected), inCaseExpected);
checkResolveStage('', '', '', '', context, expected, t);
}
// =====================================================================================================================
// Tests for configureResolveStage and isResolveStageConfigured
// =====================================================================================================================
test('configureResolveStage with all undefined', t => {
const context = {};
t.notOk(isResolveStageConfigured(context), `resolve stage settings must not be configured yet`);
// Configure it
checkConfigureResolveStage(context, undefined, undefined, undefined, undefined, undefined, false, t);
// Must NOT be able to reconfigure it with force false
checkConfigureResolveStage(context, 'convertAliasToStage', 'convertStreamNameToStage', 'streamNameStageSeparator', 'defaultStage',
'inCase', false, t);
// Must be able to reconfigure it with force true
checkConfigureResolveStage(context, 'convertAliasToStage', 'convertStreamNameToStage', 'streamNameStageSeparator', 'defaultStage',
'inCase', true, t);
t.end();
});
// =====================================================================================================================
// Tests for configureResolveStageWithDefaults and isResolveStageConfigured
// =====================================================================================================================
test('configureResolveStageWithDefaults with all undefined', t => {
const context = {};
t.notOk(isResolveStageConfigured(context), `resolve stage settings must not be configured yet`);
// Configure it
checkConfigureResolveStageWithDefaults(context, false, t);
// Overwrite it with arbitrary values to be able to check if defaults are NOT re-instated in next step
configureResolveStage(context, 'convertAliasToStage', 'convertStreamNameToStage', 'streamNameStageSeparator',
'defaultStage', 'inCase', true);
// Must NOT be able to reconfigure it with force false
checkConfigureResolveStageWithDefaults(context, false, t);
// Must be able to reconfigure it with force true
checkConfigureResolveStageWithDefaults(context, true, t);
t.end();
});
// =====================================================================================================================
// Tests for convertAliasToStage
// =====================================================================================================================
test('convertAliasToStage', t => {
checkConvertAliasToStage(undefined, '', t);
checkConvertAliasToStage(null, '', t);
checkConvertAliasToStage('', '', t);
checkConvertAliasToStage('DEV', 'DEV', t);
checkConvertAliasToStage('prod', 'prod', t);
checkConvertAliasToStage('Prod', 'Prod', t);
checkConvertAliasToStage(' QA ', 'QA', t);
checkConvertAliasToStage(' PROD 2016-10-19 ', 'PROD 2016-10-19', t);
t.end();
});
// =====================================================================================================================
// Tests for convertStreamNameSuffixToStage
// =====================================================================================================================
test('convertStreamNameSuffixToStage with default settings, should use default "_" as separator', t => {
const context = configureResolveStageWithDefaults({});
checkConvertStreamNameSuffixToStage(undefined, context, '', t);
checkConvertStreamNameSuffixToStage(null, context, '', t);
checkConvertStreamNameSuffixToStage('', context, '', t);
checkConvertStreamNameSuffixToStage('Stream1', context, '', t);
checkConvertStreamNameSuffixToStage('Stream2_', context, '', t);
checkConvertStreamNameSuffixToStage('Stream3_Dev', context, 'Dev', t);
checkConvertStreamNameSuffixToStage('Stream4_QA', context, 'QA', t);
checkConvertStreamNameSuffixToStage('Stream_5_qa', context, 'qa', t);
checkConvertStreamNameSuffixToStage('Test_Stream_6_Prod', context, 'Prod', t);
checkConvertStreamNameSuffixToStage(' Test_Stream_7_Prod-01 ', context, 'Prod-01', t);
checkConvertStreamNameSuffixToStage('Stream_SS', context, 'SS', t);
t.end();
});
test('convertStreamNameSuffixToStage with streamNameStageSeparator set to undefined, should use default "_" as separator', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.streamNameStageSeparator = undefined;
checkConvertStreamNameSuffixToStage(undefined, context, '', t);
checkConvertStreamNameSuffixToStage(null, context, '', t);
checkConvertStreamNameSuffixToStage('', context, '', t);
checkConvertStreamNameSuffixToStage('Stream1', context, '', t);
checkConvertStreamNameSuffixToStage('Stream2_', context, '', t);
checkConvertStreamNameSuffixToStage('Stream3_Dev', context, 'Dev', t);
checkConvertStreamNameSuffixToStage('Stream4_QA', context, 'QA', t);
checkConvertStreamNameSuffixToStage('Stream_5_qa', context, 'qa', t);
checkConvertStreamNameSuffixToStage('Test_Stream_6_Prod', context, 'Prod', t);
checkConvertStreamNameSuffixToStage(' Test_Stream_7_Prod-01 ', context, 'Prod-01', t);
checkConvertStreamNameSuffixToStage('Stream_SS', context, 'SS', t);
t.end();
});
test('convertStreamNameSuffixToStage with streamNameStageSeparator set to "", should still use default "_" as separator', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.streamNameStageSeparator = '';
checkConvertStreamNameSuffixToStage(undefined, context, '', t);
checkConvertStreamNameSuffixToStage(null, context, '', t);
checkConvertStreamNameSuffixToStage('', context, '', t);
checkConvertStreamNameSuffixToStage('Stream1', context, '', t);
checkConvertStreamNameSuffixToStage('Stream2_', context, '', t);
checkConvertStreamNameSuffixToStage('Stream3_Dev', context, 'Dev', t);
checkConvertStreamNameSuffixToStage('Stream4_QA', context, 'QA', t);
checkConvertStreamNameSuffixToStage('Stream_5_qa', context, 'qa', t);
checkConvertStreamNameSuffixToStage('Test_Stream_6_Prod', context, 'Prod', t);
checkConvertStreamNameSuffixToStage(' Test_Stream_7_Prod-01 ', context, 'Prod-01', t);
t.end();
});
test('convertStreamNameSuffixToStage with context.streamNameStageSeparator set to "-", should NOT use default "_" as separator', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.streamNameStageSeparator = '-';
checkConvertStreamNameSuffixToStage(undefined, context, '', t);
checkConvertStreamNameSuffixToStage(null, context, '', t);
checkConvertStreamNameSuffixToStage('', context, '', t);
checkConvertStreamNameSuffixToStage('Stream1', context, '', t);
checkConvertStreamNameSuffixToStage('Stream2_', context, '', t);
checkConvertStreamNameSuffixToStage('Stream3_Dev', context, '', t);
checkConvertStreamNameSuffixToStage('Stream3_QA', context, '', t);
checkConvertStreamNameSuffixToStage('Stream_3_qa', context, '', t);
checkConvertStreamNameSuffixToStage('Test_Stream3_Prod', context, '', t);
checkConvertStreamNameSuffixToStage(' Test_Stream3_Prod_01 ', context, '', t);
checkConvertStreamNameSuffixToStage('Stream_2-', context, '', t);
checkConvertStreamNameSuffixToStage('Stream_3-Dev', context, 'Dev', t);
checkConvertStreamNameSuffixToStage('Stream_3-QA', context, 'QA', t);
checkConvertStreamNameSuffixToStage('Stream_3-qa', context, 'qa', t);
checkConvertStreamNameSuffixToStage('Test_Stream3-Prod', context, 'Prod', t);
checkConvertStreamNameSuffixToStage(' Test_Stream3-Prod_01 ', context, 'Prod_01', t);
t.end();
});
// =====================================================================================================================
// Tests for resolveStage
// =====================================================================================================================
test('resolveStage with undefined/null/empty alias, stream name & context must return empty', t => {
const context = {};
checkResolveStage(undefined, undefined, undefined, undefined, context, '', t);
checkResolveStage(null, null, null, null, context, '', t);
checkResolveStage('', '', '', '', context, '', t);
t.end();
});
test('resolveStage with no defaultStage', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.inCase = '';
// No default stage and nothing else
checkResolveStage('', '', '', '', context, '', t);
// No default stage and stream without suffix must be empty
checkResolveStage('', '', '', 'Stream', context, '', t);
// No default stage and stream with suffix must use suffix
checkResolveStage('', '', '', 'Stream_SS', context, 'SS', t);
// No default stage and Lambda without alias must be empty
checkResolveStage('', '1.0.1', '1.0.1', '', context, '', t);
// No default stage and Lambda with alias must use alias stage
checkResolveStage('', '1.0.1', 'AS', '', context, 'AS', t);
// No default stage and event with stage must use event stage
checkResolveStage('ES', '', '', '', context, 'ES', t);
t.end();
});
test('resolveStage with defaultStage', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.inCase = '';
context.resolveStageConfig.defaultStage = 'DS';
// Default stage and nothing else must be default stage
checkResolveStage('', '', '', '', context, 'DS', t);
// Default stage must override stream without suffix
checkResolveStage('', '', '', 'Stream', context, 'DS', t);
// Default stage must not override stream with suffix
checkResolveStage('', '', '', 'Stream_SS', context, 'SS', t);
// Default stage must override Lambda without alias
checkResolveStage('', '1.0.1', '1.0.1', '', context, 'DS', t);
// Default stage must not override Lambda with alias
checkResolveStage('', '1.0.1', 'AS', '', context, 'AS', t);
// Default stage must not override event stage
checkResolveStage('ES', '', '', '', context, 'ES', t);
t.end();
});
test('resolveStage with stream without suffix', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
// Stream without suffix must not override default stage
checkResolveStage('', '', '', 'Stream', context, 'DS', t);
// Stream without suffix must not override default stage when Lambda without alias
checkResolveStage('', '1.0.1', '1.0.1', 'Stream', context, 'DS', t);
// Stream without suffix must not override Lambda with alias
checkResolveStage('', '1.0.1', 'AS', 'Stream', context, 'AS', t);
// Stream without suffix must not override event stage
checkResolveStage('ES', '', '', 'Stream', context, 'ES', t);
t.end();
});
test('resolveStage with stream with suffix', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
// Stream with suffix must override default stage
checkResolveStage('', '', '', 'Stream_SS', context, 'SS', t);
// Stream with suffix must override default stage when Lambda without alias
checkResolveStage('', '1.0.1', '1.0.1', 'Stream_SS', context, 'SS', t);
// Stream with suffix must not override Lambda with alias
checkResolveStage('', '1.0.1', 'AS', 'Stream_SS', context, 'AS', t);
// Stream with suffix must not override event stage
checkResolveStage('ES', '', '', 'Stream_SS', context, 'ES', t);
t.end();
});
test('resolveStage with Lambda without alias', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
// Lambda without alias must not override default stage
checkResolveStage('', '1.0.1', '1.0.1', '', context, 'DS', t);
// Lambda without alias must not override default stage when stream without suffix
checkResolveStage('', '1.0.1', '1.0.1', 'Stream', context, 'DS', t);
// Lambda without alias must not override stream with suffix
checkResolveStage('', '1.0.1', '1.0.1', 'Stream_SS', context, 'SS', t);
// Lambda without alias must not override event stage
checkResolveStage('ES', '1.0.1', '1.0.1', 'Stream_SS', context, 'ES', t);
t.end();
});
test('resolveStage with Lambda with alias', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
// Lambda with alias must override default stage
checkResolveStage('', '1.0.1', 'AS', '', context, 'AS', t);
// Lambda with alias must override default stage when stream without suffix
checkResolveStage('', '1.0.1', 'AS', 'Stream', context, 'AS', t);
// Lambda with alias must override stream with suffix
checkResolveStage('', '1.0.1', 'AS', 'Stream_SS', context, 'AS', t);
// Lambda with alias must not override event stage
checkResolveStage('ES', '1.0.1', 'AS', 'Stream_SS', context, 'ES', t);
t.end();
});
test('resolveStage with event stage', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
// Event stage must override default stage
checkResolveStage('ES', '', '', '', context, 'ES', t);
// Event stage must override stream without suffix and default
checkResolveStage('ES', '', '', 'Stream', context, 'ES', t);
// Event stage must override stream with suffix and default
checkResolveStage('ES', '', '', 'Stream_SS', context, 'ES', t);
// Event stage must override Lambda without alias and default
checkResolveStage('ES', '1.0.1', '1.01', '', context, 'ES', t);
// Event stage must override Lambda without alias and stream without suffix and default
checkResolveStage('ES', '1.0.1', '1.01', 'Stream', context, 'ES', t);
// Event stage must override Lambda without alias and stream with suffix and default
checkResolveStage('ES', '1.0.1', '1.01', 'Stream_SS', context, 'ES', t);
// Event stage must override Lambda with alias and default
checkResolveStage('ES', '1.0.1', 'AS', '', context, 'ES', t);
// Event stage must override Lambda with alias and stream without suffix and default
checkResolveStage('ES', '1.0.1', 'AS', 'Stream', context, 'ES', t);
// Event stage must override Lambda with alias and stream with suffix and default
checkResolveStage('ES', '1.0.1', 'AS', 'Stream_SS', context, 'ES', t);
t.end();
});
test('resolveStage with context stage and without event stage', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
context.stage = 'CS';
// Context stage must override default stage
checkResolveStage('', '', '', '', context, 'CS', t);
// Context stage must override stream without suffix and default
checkResolveStage('', '', '', 'Stream', context, 'CS', t);
// Context stage must override stream with suffix and default
checkResolveStage('', '', '', 'Stream_SS', context, 'CS', t);
// Context stage must override Lambda without alias and default
checkResolveStage('', '1.0.1', '1.01', '', context, 'CS', t);
// Context stage must override Lambda without alias and stream without suffix and default
checkResolveStage('', '1.0.1', '1.01', 'Stream', context, 'CS', t);
// Context stage must override Lambda without alias and stream with suffix and default
checkResolveStage('', '1.0.1', '1.01', 'Stream_SS', context, 'CS', t);
// Context stage must override Lambda with alias and default
checkResolveStage('', '1.0.1', 'AS', '', context, 'CS', t);
// Context stage must override Lambda with alias and stream without suffix and default
checkResolveStage('', '1.0.1', 'AS', 'Stream', context, 'CS', t);
// Context stage must override Lambda with alias and stream with suffix and default
checkResolveStage('', '1.0.1', 'AS', 'Stream_SS', context, 'CS', t);
t.end();
});
test('resolveStage with context stage and with event stage', t => {
const context = configureResolveStageWithDefaults({});
context.resolveStageConfig.defaultStage = 'DS';
context.resolveStageConfig.inCase = '';
context.stage = 'CS';
// Context stage must override default stage
checkResolveStage('ES', '', '', '', context, 'CS', t);
// Context stage must override stream without suffix and default
checkResolveStage('ES', '', '', 'Stream', context, 'CS', t);
// Context stage must override stream with suffix and default
checkResolveStage('ES', '', '', 'Stream_SS', context, 'CS', t);
// Context stage must override event stage and Lambda without alias and default
checkResolveStage('ES', '1.0.1', '1.01', '', context, 'CS', t);
// Context stage must override event stage and Lambda without alias and stream without suffix and default
checkResolveStage('ES', '1.0.1', '1.01', 'Stream', context, 'CS', t);
// Context stage must override event stage and Lambda without alias and stream with suffix and default
checkResolveStage('ES', '1.0.1', '1.01', 'Stream_SS', context, 'CS', t);
// Context stage must override event stage and Lambda with alias and default
checkResolveStage('ES', '1.0.1', 'AS', '', context, 'CS', t);
// Context stage must override event stage and Lambda with alias and stream without suffix and default
checkResolveStage('ES', '1.0.1', 'AS', 'Stream', context, 'CS', t);
// Context stage must override event stage and Lambda with alias and stream with suffix and default
checkResolveStage('ES', '1.0.1', 'AS', 'Stream_SS', context, 'CS', t);
t.end();
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc