lambda-live-debugger
Version:
Debug Lambda functions locally like it is running in the cloud
119 lines (118 loc) • 4.02 kB
JavaScript
import { AwsCredentials } from './awsCredentials.mjs';
import { Logger } from './logger.mjs';
import * as yaml from 'yaml';
let cloudFormationClient;
/**
* Get CloudFormation stack template
* @param stackName
* @param awsConfiguration
* @returns
*/
async function getCloudFormationStackTemplate(stackName, awsConfiguration) {
const { GetTemplateCommand } = await import('@aws-sdk/client-cloudformation');
const command = new GetTemplateCommand({ StackName: stackName });
const cloudFormationClient = await getCloudFormationClient(awsConfiguration);
try {
const response = await cloudFormationClient.send(command);
if (!response.TemplateBody) {
throw new Error(`No template found for stack ${stackName}`);
}
let cfTemplate;
try {
cfTemplate = JSON.parse(response.TemplateBody);
}
catch (parseError) {
if (parseError.message.includes('is not valid JSON')) {
// If the template is not JSON, try parsing it as YAML
cfTemplate = yaml.parse(response.TemplateBody);
}
else {
throw parseError;
}
}
return cfTemplate;
}
catch (error) {
if (error.name === 'ValidationError') {
Logger.error(`Stack ${stackName} not found. Try specifying a region. Error: ${error.message}`, error);
return undefined;
}
else {
throw error;
}
}
}
/**
* Get CloudFormation client
* @param awsConfiguration
* @returns
*/
async function getCloudFormationClient(awsConfiguration) {
if (!cloudFormationClient) {
const { CloudFormationClient } = await import('@aws-sdk/client-cloudformation');
cloudFormationClient = new CloudFormationClient({
region: awsConfiguration.region,
credentials: AwsCredentials.getCredentialsProvider(awsConfiguration),
});
}
return cloudFormationClient;
}
/**
* Get CloudFormation resources
* @param stackName
* @param awsConfiguration
* @returns
*/
async function getCloudFormationResources(stackName, awsConfiguration) {
// temporary disable console.error because SAM framework outputs useless errors
const originalConsoleError = console.error;
console.error = function () { };
const { ListStackResourcesCommand } = await import('@aws-sdk/client-cloudformation');
console.error = originalConsoleError;
const cloudFormationClient = await getCloudFormationClient(awsConfiguration);
try {
let nextToken = undefined;
const items = [];
do {
const command = new ListStackResourcesCommand({
StackName: stackName,
NextToken: nextToken,
});
const response = await cloudFormationClient.send(command);
if (response.StackResourceSummaries) {
items.push(...response.StackResourceSummaries);
}
nextToken = response.NextToken;
} while (nextToken);
return items;
}
catch (error) {
if (error.name === 'ValidationError') {
Logger.error(`Stack ${stackName} not found. Try specifying a region. Error: ${error.message}`, error);
return undefined;
}
else {
throw error;
}
}
}
/**
* Get Lambdas in stack
* @param stackName
* @param awsConfiguration
* @returns
*/
async function getLambdasInStack(stackName, awsConfiguration) {
const response = await getCloudFormationResources(stackName, awsConfiguration);
const lambdaResources = response?.filter((resource) => resource.ResourceType === 'AWS::Lambda::Function');
return (lambdaResources?.map((resource) => {
return {
lambdaName: resource.PhysicalResourceId,
logicalId: resource.LogicalResourceId,
};
}) ?? []);
}
export const CloudFormation = {
getCloudFormationStackTemplate,
getLambdasInStack,
};