I have created the following user schema, including two methods:
getSnapshot()
getLastTweetId()
user.js
const mongoose = require('mongoose')
const getLastTweetId = require('../utilities/getLastTweetId')
const getFollowers = require('../utilities/getFollowers')
const userSchema = new mongoose.Schema({
twitterId: {
type: String,
required: true
},
screenName: {
type: String
},
snapshots: {
type: [snapshotSchema],
default: []
},
createdAt: {
type: Date
},
})
userSchema.method('getSnapshot', async function () {
const { user, snapshot } = await getFollowers({user: this})
await user.save()
return snapshot
})
userSchema.method('getLastTweetId', async function () {
const tweetId = await getLastTweetId({user: this})
return tweetId
})
const User = mongoose.model('User', userSchema)
module.exports = User
When I define a user instance in passport.js, I can call getSnapshot() on user with no problems. (see below)
passport.js
const passport = require('passport')
const mongoose = require('mongoose')
const needle = require('needle')
const { DateTime } = require('luxon')
const User = mongoose.model('User')
// Setup Twitter Strategy
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_API_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_API_SECRET_KEY,
callbackURL: process.env.CALLBACK_URL,
proxy: trustProxy
},
async (token, tokenSecret, profile, cb) => {
const twitterId = profile.id
const screenName = profile.screen_name
const existingUser = await User.findOne({ twitterId })
if (existingUser) {
// Track if this is a new login from an existing user
if (existingUser.screenName !== screenName) {
existingUser.screenName = screenName
await existingUser.save()
}
// we already have a record with the given profile ID
cb(undefined, existingUser)
} else {
// we don't have a user record with this ID, make a new record
const user = await new User ({
twitterId ,
screenName,
}).save()
**user.getSnapshot()**
cb(undefined, user)
}
}
)
However, when I call getLastTweetId() on a user instance in tweet.js, I receive the following error in my terminal:
TypeError: user.getLastTweetId is not a function
Then my app crashes.
tweets.js
const express = require('express')
const mongoose = require('mongoose')
const User = mongoose.model('User')
const Tweet = mongoose.model('Tweet')
const { DateTime } = require('luxon')
const auth = require('../middleware/auth')
const requestTweets = require('../utilities/requestTweets')
const router = new express.Router()
const getRecentTweets = async (req, res) => {
const twitterId = req.user.twitterId
const user = await User.find({twitterId})
*const sinceId = user.getLastTweetId()*
let params = {
'start_time': `${DateTime.now().plus({ month: -2 }).toISO({ includeOffset: false })}Z`,
'end_time': `${DateTime.now().toISO({ includeOffset: false })}Z`,
'max_results': 100,
'tweet.fields': "created_at,entities"
}
if (sinceId) {
params.since_id = sinceId
}
let options = {
headers: {
'Authorization': `Bearer ${process.env.TWITTER_BEARER_TOKEN}`
}
}
const content = await requestTweets(twitterId, params, options)
const data = content.data
const tweets = data.map((tweet) => (
new Tweet({
twitterId,
tweetId: tweet.id,
text: tweet.text,
})
))
tweets.forEach(async (tweet) => await tweet.save())
}
// Get all tweets of one user either since last retrieved tweet or for specified month
router.get('/tweets/user/recent', auth, getRecentTweets)
module.exports = router
I would really appreciate some support to figure out what is going on here.
Thank you for bearing with me!
My first guess was that the user instance is not created properly in tweets.js, but then I verified via log messages that the user instance is what I expect it to be in both passport.js as well as tweets.js
My second guess was that the problem is that the user instance in the database was created before I added the new method to the schema, but deleting and reinstantiating the entire collection in the db changed nothing.
Next I went about checking if the issue is related to instantiating the schema itself or just importing it and it seems to be the latter, since when I call getLastTweetId in passport.js it also works, when I call getSnapshot() in tweets.js it also fails.
This is where I'm stuck, because as far as I can tell, I am requiring the User model exactly the same way in both files.
Even when I print User.schema.methods in either file, it shows the following:
[0] {
[0] getSnapshot: [AsyncFunction (anonymous)],
[0] getLastTweetId: [AsyncFunction (anonymous)]
[0] }
It looks like my first guess regarding what was wrong was on point, and I was just sloppy in verifying that I'm instantiating the user correctly.
const user = await User.find({twitterId})
The above line was returning an array of users.
Instead, I should have called:
const user = await User.findOne({twitterId})
I did not detect the bug at first, because logging an array that contains only one object looks nearly the same as just logging the object itself, I simply overlooked the square brackets.
Changing that single line fixed it.
I'm using a Lambda function which gets me the user email from a user id within a dynamoDB table. I use the dynamoDB scan command to scan over all items within the dynamoDB table. I use the new v3 AWS JS SDK.
Question: Why does ExpressionAttributeNames not work properly in my case?
This works:
const params = {
FilterExpression: "user_info.user_id = :userid",
ExpressionAttributeValues: {
":userid": { S: user_id }
},
ProjectionExpression: "user_email",
TableName: aws_table,
}
But this does NOT work, why?
const params = {
FilterExpression: "#xyz = :userid",
ExpressionAttributeNames: {
"#xyz": "user_info.user_id" // <- filter does not work like this (returns 0 findings)
},
ExpressionAttributeValues: {
":userid": { S: user_id }
},
ProjectionExpression: "user_email",
TableName: aws_table,
};
My Lambda scan operation code itself looks like:
const { DynamoDBClient } = require("#aws-sdk/client-dynamodb");
const { ScanCommand } = require("#aws-sdk/client-dynamodb");
const ddbClient = new DynamoDBClient({ region: aws_region });
...
const run = async () => {
try {
const data = await ddbClient.send(new ScanCommand(params));
data.Items.forEach(function (element, index, array) {
console.log(element);
});
return data;
} catch (err) {
console.log("Error", err);
}
}
await run();
npm i #aws-sdk/client-dynamodb
Documentation:
https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/interfaces/scancommandinput.html#expressionattributenames
This is the expected behaviour:
DynamoDB interprets a dot in an expression attribute name as a character within an attribute's name
// use multiple expression attribute names if you need a dynamic path:
FilterExpression: "#user_info.#user_id = :userid"
I have a Lambda that I have created using the AWS Toolkit for Visual Studio Code. I have a small lambda.js file that exports the handler for API Gateway events.
const App = require('./app');
const AWS = require('aws-sdk');
exports.handler = async (event, context) => {
let config = {
aws_region: 'us-east-1',
//endpoint: 'http://localhost:8000',
};
let dynamo = new AWS.DynamoDB.DocumentClient();
let app = new App(dynamo, config, event);
try {
let response = await app.run();
return response;
} catch(err) {
return err;
}
};
The app.js file represents the logic of my Lambda. This is broken up to improve testing.
const AWS = require('aws-sdk');
class App {
constructor(datastore, configuration, event) {
this.datastore = datastore;
this.httpEvent = event;
this.configuration = configuration;
}
async run() {
AWS.config.update({
region: this.configuration.aws_region,
endpoint: this.configuration.endpoint,
});
let params = {
TableName: 'test',
Key: {
'year': 2015,
'title': 'The Big New Movie',
},
};
const getRequest = this.datastore.get(params);
// EXCEPTION THROWN HERE
var result = await getRequest.promise();
let body = {
location: this.configuration.aws_region,
url: this.configuration.endpoint,
data: result
};
return {
'statusCode': 200,
'body': JSON.stringify(body)
};
}
}
module.exports = App;
I can write the following mocha test and get it to pass.
'use strict';
const AWS = require('aws-sdk');
const chai = require('chai');
const sinon = require('sinon');
const App = require('../app');
const expect = chai.expect;
var event, context;
const dependencies = {
// sinon.stub() prevents calls to DynamoDB and allows for faking of methods.
dynamo: sinon.stub(new AWS.DynamoDB.DocumentClient()),
configuration: {
aws_region: 'us-west-2',
endpoint: 'http://localhost:5000',
},
};
describe('Tests handler', function () {
// Reset test doubles for isolating individual test cases
this.afterEach(sinon.reset);
it('verifies successful response', async () => {
dependencies.dynamo.get.returns({ promise: sinon.fake.resolves('foo bar')});
let app = new App(dependencies.dynamo, dependencies.configuration, event);
const result = await app.run()
expect(result).to.be.an('object');
expect(result.statusCode).to.equal(200);
expect(result.body).to.be.an('string');
console.log(result.body);
let response = JSON.parse(result.body);
expect(response).to.be.an('object');
expect(response.location).to.be.equal(dependencies.configuration.aws_region);
expect(response.url).to.be.equal(dependencies.configuration.endpoint);
expect(response.data).to.be.equal('foo bar');
});
});
However, when I run the Lambda locally using the Debug Locally via the Code Lens option in VS Code the results from the AWS.DynamoDB.DocumentClient.get call throws an exception.
{
"message":"The provided key element does not match the schema",
"code":"ValidationException",
...
"statusCode":400,
"retryable":false,
"retryDelay":8.354173589804192
}
I have a table created in the us-east-1 region where the non-test code is configured to go to. I've confirmed the http endpoint being hit by the DocumentClient as being dynamodb.us-east-1.amazonaws.com. The table name is correct and I have a hash key called year and a sort key called title. Why would this not find the key correctly? I pulled this example from the AWS documentation, created a table to mirror what the key was and have not had any luck.
The issue is that the Key year was provided a number value while the table was expecting it to be a string.
Wrapping the 2015 in quotes let the Document know that this was a string and it could match to the schema in Dynamo.
let params = {
TableName: 'test',
Key: {
'year': '2015',
'title': 'The Big New Movie',
},
};
I'm trying to create an API gateway using the AWS-CDK and protect the REST endpoints with a Cognito user pool authorizer.
I cannot find any examples how one would do this. I thought it should look something like this but maybe the methods I need do not exist?
const cdk = require('#aws-cdk/cdk');
const lambda = require('#aws-cdk/aws-lambda');
const apigw = require('#aws-cdk/aws-apigateway');
const path = require('path');
//
// Define the stack:
class MyStack extends cdk.Stack {
constructor (parent, id, props) {
super(parent, id, props);
var tmethodHandler = new lambda.Function(this, 'test-lambda', {
runtime: lambda.Runtime.NodeJS810,
handler: 'index.handler',
code: lambda.Code.directory( path.join( __dirname, 'lambda')),
});
var api = new apigw.RestApi(this, 'test-api');
const tmethod = api.root.addResource('testmethod');
const tmethodIntegration = new apigw.LambdaIntegration(tmethodHandler);
tmethod.addMethod('GET', getSessionIntegration, {
authorizationType: apigw.AuthorizationType.Cognito,
authorizerId : 'crap!!!?'
});
}
}
class MyApp extends cdk.App {
constructor (argv) {
super(argv);
new MyStack(this, 'test-apigw');
}
}
console.log(new MyApp(process.argv).run());
As of September 2019 #bgdnip answer doesnt translate exactly for typescript. I got it working with the following:
const api = new RestApi(this, 'RestAPI', {
restApiName: 'Rest-Name',
description: 'API for journey services.',
});
const putIntegration = new LambdaIntegration(handler);
const auth = new CfnAuthorizer(this, 'APIGatewayAuthorizer', {
name: 'customer-authorizer',
identitySource: 'method.request.header.Authorization',
providerArns: [providerArn.valueAsString],
restApiId: api.restApiId,
type: AuthorizationType.COGNITO,
});
const post = api.root.addMethod('PUT', putIntegration, { authorizationType: AuthorizationType.COGNITO });
const postMethod = post.node.defaultChild as CfnMethod;
postMethod.addOverride('Properties.AuthorizerId', { Ref: auth.logicalId });
This is from https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_resource_props
UPDATE October
The above is already out of date and unnecessary and can be achieved with the following with aws-cdk 1.12.0
const api = new RestApi(this, 'RestAPI', {
restApiName: 'Rest-Name',
description: 'API for journey services.',
});
const putIntegration = new LambdaIntegration(handler);
const auth = new CfnAuthorizer(this, 'APIGatewayAuthorizer', {
name: 'customer-authorizer',
identitySource: 'method.request.header.Authorization',
providerArns: [providerArn.valueAsString],
restApiId: api.restApiId,
type: AuthorizationType.COGNITO,
});
const post = api.root.addMethod('PUT', putIntegration, {
authorizationType: AuthorizationType.COGNITO,
authorizer: { authorizerId: auth.ref }
});
The previous answers no longer work because the authorizerId property was replaced with authorizer, which isn't fully implemented at this time.
Instead, it can be done by using the underlying CfnResource objects, as described in the official guide.
Here's Python code as an example:
from aws_cdk import cdk
from aws_cdk import aws_apigateway
class Stk(cdk.Stack):
def __init__(self, app, id):
super().__init__(app, id)
api_gw = aws_apigateway.RestApi(self, 'MyApp')
post_method = api_gw.root.add_method(http_method='POST')
# Create authorizer using low level CfnResource
api_gw_authorizer = aws_apigateway.CfnAuthorizer(
scope=self,
id='my_authorizer',
rest_api_id=api_gw.rest_api_id,
name='MyAuth',
type='COGNITO_USER_POOLS',
identity_source='method.request.header.name.Authorization',
provider_arns=[
'arn:aws:cognito-idp:eu-west-1:123456789012:userpool/'
'eu-west-1_MyCognito'])
# Get underlying post_method Resource object. Returns CfnMethod
post_method_resource = post_method.node.find_child('Resource')
# Add properties to low level resource
post_method_resource.add_property_override('AuthorizationType',
'COGNITO_USER_POOLS')
# AuthorizedId uses Ref, simulate with a dictionaty
post_method_resource.add_property_override(
'AuthorizerId',
{"Ref": api_gw_authorizer.logical_id})
app = cdk.App()
stk = Stk(app, "myStack")
app.synth()
This is my solution in TypeScript (based somewhat on bgdnlp's response)
import { App, Stack, Aws } from '#aws-cdk/core';
import { Code, Function, Runtime } from '#aws-cdk/aws-lambda';
import { LambdaIntegration, RestApi, CfnAuthorizer, CfnMethod } from '#aws-cdk/aws-apigateway';
const app = new App();
const stack = new Stack(app, `mystack`);
const api = new RestApi(stack, `myapi`);
const region = Aws.REGION;
const account = Aws.ACCOUNT_ID;
const cognitoArn = `arn:aws:cognito-idp:${region}:${account}:userpool/${USER_POOL_ID}`;
const authorizer = new CfnAuthorizer(stack, 'Authorizer', {
name: `myauthorizer`,
restApiId: api.restApiId,
type: 'COGNITO_USER_POOLS',
identitySource: 'method.request.header.Authorization',
providerArns: [cognitoArn],
});
const lambda = new Function(stack, 'mylambda', {
runtime: Runtime.NODEJS_10_X,
code: Code.asset('dist'),
handler: `index.handler`,
});
const integration = new LambdaIntegration(lambda);
const res = api.root.addResource('hello');
const method = res.addMethod('GET', integration);
const child = method.node.findChild('Resource') as CfnMethod;
child.addPropertyOverride('AuthorizationType', 'COGNITO_USER_POOLS');
child.addPropertyOverride('AuthorizerId', { Ref: authorizer.logicalId });
Indeed. there is no example to do this via copy and paste ;). here is my example to create AWS cognito user pool and connect user pol authorizer with API gateway and lambda function using AWS CDK based on Java with Version 0.24.1.
This example ist just an example to provide an protected API for function called "Foo".
Cognito User Pool
API Gateway
Lambda
DynamoDB
// -----------------------------------------------------------------------
// Cognito User Pool
// -----------------------------------------------------------------------
CfnUserPool userPool = new CfnUserPool(this, "cognito",
CfnUserPoolProps.builder()
.withAdminCreateUserConfig(
AdminCreateUserConfigProperty.builder()
.withAllowAdminCreateUserOnly(false)
.build())
.withPolicies(
PoliciesProperty.builder()
.withPasswordPolicy(
PasswordPolicyProperty.builder()
.withMinimumLength(6)
.withRequireLowercase(false)
.withRequireNumbers(false)
.withRequireSymbols(false)
.withRequireUppercase(false)
.build()
)
.build()
)
.withAutoVerifiedAttributes(Arrays.asList("email"))
.withSchema(Arrays.asList(
CfnUserPool.SchemaAttributeProperty.builder()
.withAttributeDataType("String")
.withName("email")
.withRequired(true)
.build()))
.build());
// -----------------------------------------------------------------------
// Cognito User Pool Client
// -----------------------------------------------------------------------
new CfnUserPoolClient(this, "cognitoClient",
CfnUserPoolClientProps.builder()
.withClientName("UserPool")
.withExplicitAuthFlows(Arrays.asList("ADMIN_NO_SRP_AUTH"))
.withRefreshTokenValidity(90)
.withUserPoolId(userPool.getRef())
.build());
// -----------------------------------------------------------------------
// Lambda function
// -----------------------------------------------------------------------
Function function = new Function(this, "function.foo",
FunctionProps.builder()
// lamda code located in /functions/foo
.withCode(Code.asset("functions/foo"))
.withHandler("index.handler")
.withRuntime(Runtime.NODE_J_S810)
.build());
// -----------------------------------------------------------------------
// DynamoDB Table
// -----------------------------------------------------------------------
Table table = new Table(this, "dynamodb.foo", TableProps.builder()
.withTableName("foo")
.withPartitionKey(Attribute.builder()
.withName("id")
.withType(AttributeType.String)
.build())
.build());
// GRANTS function -> table
table.grantReadWriteData(function.getRole());
// -----------------------------------------------------------------------
// API Gateway
// -----------------------------------------------------------------------
// API Gateway REST API with lambda integration
LambdaIntegration lambdaIntegration = new LambdaIntegration(function);
RestApi restApi = new RestApi(this, "foo");
// Authorizer configured with cognito user pool
CfnAuthorizer authorizer = new CfnAuthorizer(this, "authorizer",
CfnAuthorizerProps.builder()
.withName("cognitoAuthorizer")
.withRestApiId(restApi.getRestApiId())
.withIdentitySource("method.request.header.Authorization")
.withProviderArns(Arrays.asList(userPool.getUserPoolArn()))
.withType("COGNITO_USER_POOLS")
.build());
// Bind authorizer to API ressource
restApi.getRoot().addMethod("ANY", lambdaIntegration, MethodOptions
.builder()
.withAuthorizationType(AuthorizationType.Cognito)
.withAuthorizerId(authorizer.getAuthorizerId())
.build());
I figured out what looks like a mechanism... I was able to get it to work like this:
var auth = new apigw.cloudformation.AuthorizerResource(this, 'myAuthorizer', {
restApiId: api.restApiId,
authorizerName: 'mypoolauth',
authorizerResultTtlInSeconds: 300,
identitySource: 'method.request.header.Authorization',
providerArns: [ 'arn:aws:cognito-idp:us-west-2:redacted:userpool/redacted' ],
type: "COGNITO_USER_POOLS"
});
tmethod.addMethod('GET', getSessionIntegration, {
authorizationType: apigw.AuthorizationType.Cognito,
authorizerId : auth.authorizerId
});
Now to figure out how to enable CORS headers on API Gateway...
You have to:
create the api gateway
set Cognito as authorizer in the api gateway
set the authorization in your method
set your integration with the lambda to 'Use Lambda Proxy integration'. The LambdaIntegration properties has on true this value by default, so don't worry for it
Finally, make a request adding the token in the Header. The API gateway will validate it with Cognito. If this pass then, your lambda will be triggered and in the event you can find the claims event.requestContext.authorizer.claims.
const lambda = require("#aws-cdk/aws-lambda");
const apiGateway = require('#aws-cdk/aws-apigateway');
const api = new apiGateway.RestApi(
this,
'<id-ApiGateway>',
{
restApiName: '<ApiGateway-name>',
},
);
const auth = new apiGateway.CfnAuthorizer(this, '<id>', {
name: "<authorizer-name>",
type: apiGateway.AuthorizationType.COGNITO,
authorizerResultTtlInSeconds: 300,
identitySource: "method.request.header.Authorization",
restApiId: api.restApiId,
providerArns: ['<userPool.userPoolArn>'],
});
const myLambda= new lambda.Function(this, "<id>", {
functionName: '<lambda-name>',
runtime: lambda.Runtime.NODEJS_10_X,
handler: "<your-handler>",
code: lambda.Code.fromAsset("<path>"), // TODO: modify the way to get the path
});
const lambdaIntegration = new apiGateway.LambdaIntegration(myLambda);
const resource = api.root.resourceForPath('<your-api-path>');
// When the API will be deployed, the URL will look like this
// https://xxxxxx.execute-api.us-east-2.amazonaws.com/dev/<your-api-path>
const authorizationOptions = {
apiKeyRequired: false,
authorizer: {authorizerId: auth.ref},
authorizationType: 'COGNITO_USER_POOLS'
};
resource.addMethod(
GET, // your method
lambdaIntegration,
authorizationOptions
);
For the weirdos using the Java version of the CDK (like me), you can utilize the setters on the Cfn constructs:
final UserPool userPool = ...
final RestApi restApi = ...
final LambdaIntegration integration = ...
final Method method = restApi.getRoot().addMethod("GET", integration);
final CfnAuthorizer cognitoAuthorizer = new CfnAuthorizer(this, "CfnCognitoAuthorizer",
CfnAuthorizerProps.builder()
.name("CognitoAuthorizer")
.restApiId(restApi.getRestApiId())
.type("COGNITO_USER_POOLS")
.providerArns(Arrays.asList(userPool.getUserPoolArn()))
.identitySource("method.request.header.Authorization")
.build());
final CfnMethod cfnMethod = (CfnMethod) method.getNode().getDefaultChild();
cfnMethod.setAuthorizationType("COGNITO_USER_POOLS");
cfnMethod.setAuthorizerId(cognitoAuthorizer.getRef());
As of v1.88 this is now supported directly in CDK
const userPool = new cognito.UserPool(this, 'UserPool');
const auth = new apigateway.CognitoUserPoolsAuthorizer(this, 'booksAuthorizer', {
cognitoUserPools: [userPool]
});
declare const books: apigateway.Resource;
books.addMethod('GET', new apigateway.HttpIntegration('http://amazon.com'), {
authorizer: auth,
authorizationType: apigateway.AuthorizationType.COGNITO,
});
AWS CDK API V1 Reference
AWS CDK API V2 Reference
If you are currently using CDK v2 or CDK v1(latest). This has been made easy:
// Your cognito userpool
const userPool = new cognito.UserPool(this, "MyUserPool")
// Authorizer for your userpool
const cognitoAuthorizer = new apigw.CognitoUserPoolsAuthorizer(
this,
"CognitoAuthorierOnLambda",
{
cognitoUserPools: [userPool],
}
);
// Rest Api
const api = new apigw.RestApi(this, 'myApi', {
defaultCorsPreflightOptions: {
allowOrigins: apigw.Cors.ALL_ORIGINS,
allowMethods: apigw.Cors.ALL_METHODS, // this is also the default
},
deploy: true
});
// add /getItems endpoint
const getItems = api.root.addResource('getItems');
// attach lambda to this endpoint
const getItemsIntegration = new apigw.LambdaIntegration(getItemsLambdaFunction);
// make the endpoint secure with cognito userpool
getItems.addMethod('GET', getAllItemsIntegration, {
authorizer:cognitoAuthorizer
});
I am somewhat new to Lambda and am trying to pull some data from Support(us-east-1) and then Read/Write to a DynamoDB(I am using a local dynamodb-local instance), however I dont know how to change the region.
const AWS = require('aws-sdk');
AWS.config.update({
region: 'us-east-1',
});
const support = new AWS.Support({
region: 'us-east-1',
apiVersion: '2013-04-15'
});
const supportParams = {
checkId: 'Qch7DwouX1',
language: 'en'
};
let stuff = {};
support.describeTrustedAdvisorCheckResult(supportParams, (err, data) => {
if(err) console.log('Error: ', err.stack);
else {
stuff[test] = [...data]
};
}
// Now I want to pull some data from DynamoDB locally or in another region
//
// AWS.config.update({endpoint: 'http://localhost:8000});
//
How do I change the endpoint to http://localhost:8000 or us-west-2 to get something from DynamoDB? Am I not supposed to change region/endpoint within 1 lambda function?
I was trying something like:
const dynaDB = new AWS.DynamoDB({endpoint: 'http://localhost:8000'})
const dynaClient = new AWS.DynamoDB.DocumentClient();
dynaClient.scan({}, (err, data) => {
..
..
..
}
We had the same problem when we want to copy between two regions.
You can instantiate aws-sdk one for each dynamodb,
const AWSregion = require('aws-sdk');
AWSregion.config.update({
region: 'us-east-1',
});
// Connect to us-east-1 with AWSregion
const AWSlocal = require('aws-sdk'); // Don't set any region here, since it is local
// Connect to local dynamodb with AWSlocal
Hope it helps.