AWS S3Client throws error: 'emitWarning' is not a function - node.js

I am trying to create an S3Client using the #aws-sdk/client-s3 package, as shown below:
const { S3Client } = require('#aws-sdk/client-s3')
const client = new S3Client({ region: 'us-east-1' })
It runs fine locally, but when I upload the code to a MongoDB Realm function along with the client-s3 dependency, it throws the error: {"message":"'emitWarning' is not a function","name":"TypeError"}
What might be causing this error?

It turns out this was happening because the MongoDB Realm Functions environment does not have an emitWarning function defined on the global process variable, which is why the error kept saying 'emitWarning' is not a function.
I reached out to MongoDB Support about this, and apparently the AWS-SDK v3 just isn't compatible with MongoDB Realm Functions.
Instead, you must use the AWS-SDK v2. I eventually found this MongoDB Forums Article, which explained that they specifically support v2.737.0 of the SDK.

Related

Failed attempts to write to DynamoDB Local

I recently discovered DynamoDB Local and started building it into my project for local development. I decided to go the docker image route (as opposed to the downloadable .jar file.
That being said I've gotten image up and running and have created a table and can successfully interact with the docker container via the aws cli. aws dynamodb list-tables --endpoint-url http://localhost:8042 successfully returns the table I created previously.
However, when I run my lambda function and set my aws config like so.
const axios = require('axios')
const cheerio = require('cheerio')
const randstring = require('randomstring')
const aws = require('aws-sdk')
const dynamodb = new aws.DynamoDB.DocumentClient()
exports.lambdaHandler = async (event, context) => {
let isLocal = process.env.AWS_SAM_LOCAL
if (isLocal) {
aws.config.update({
endpoint: new aws.Endpoint("http://localhost:8042")
})
}
(which I have confirmed is getting set) it actually writes to the table (with the same name of the local dynamodb instance) in the live AWS Webservice as opposed to the local container and table.
It's also worth mentioning I'm unable to connect to the local instance of DynamoDB with the AWS NoSQL Workbench tool even though it's configured to point to http://localhost:8042 as well...
Am I missing something? Any help would be greatly appreciated. I can provide any more information if I haven't already done so as well :D
Thanks.
SDK configuration changes, such as region or endpoint, do not retroactively apply to existing clients (regular DynamoDB client or a document client).
So, change the configuration first and then create your client object. Or simply pass the configuration options into the client constructor.

How do i reference Firebase's realtime database from within a cloud function?

In a Firebase Cloud function i am attempting to retrieve data from my Realtime Database and write an update to it as well. This is where i am having trouble.
The function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
...
api.post('/messages/add', (request: any, response: any) => {
const dbRef:any = functions.database.ref(`count/${request.body.chatRoomId}`);
dbRef.once('value').then((snapshot:any) => {
let messageCount:number = (snapshot.val() && snapshot.val().messages) || 0;
messageCount = Number(messageCount + 1);
dbRef.update({
messages: messageCount,
updated: admin.database().database.ServerValue.TIMESTAMP
});
});
});
When i call this function from the client, in the firebase cloud console logs, i am seeing the following error:
TypeError: dbRef.once is not a function
I have tried referencing the database in each of the following ways, all of which fail:
functions.database.ref(`count/${request.body.chatRoomId}`).once('value').then((snapshot)) =>
functions.database.ref(`count/${request.body.chatRoomId}`).once('value', (snapshot) =>
admin.database().ref(`count/${request.body.chatRoomId}`).once('value').then((snapshot)) =>
admin.database().ref(`count/${request.body.chatRoomId}`).once('value', (snapshot) =>
When attempting the reference using the Admin SDK via admin.database() i get a different error:
TypeError: Cannot read property 'ServerValue' of undefined
at dbRef.once.then
Lastly, i can confirm that the value for ${request.body.chatRoomId} is resolving correctly, i had tested this by printing its value to the console.
The answer here shows how to reference the realtime database from the 'event' response within a realtime database listener like onWrite() for example, however my function is not triggered by realtime database changes, but rather is an endpoint reachable from the client.
UPDATE
The answer proposed by Doug Stevenson below is correct but there was also an additional error due to attempting to write a timestamp incorrectly to a field that i had initially excluded which was causing my function to fail despite having tried his solution, thus I have updated the code to reflect this.
First, the answer is to reference the Realtime Database with admin.database()
Second, even though i had tried this, i was still seeing an error, but the error was due to attempting to set a timestamp incorrectly. Thanks to Frank van Puffelen for pointing this out.
This: admin.database().database.ServerValue.TIMESTAMP
Needs to be: admin.database.ServerValue.TIMESTAMP
And with that it works.
You're making the mistake of trying to use the functions SDK to query the database. This is not actually creating a database reference:
functions.database.ref(`count/${request.body.chatRoomId}`);
The functions SDK is just used for declaring and configuring Cloud Functions.
What you should be doing instead is using the Admin SDK to create a reference, then query it:
admin.database().ref(...).once(...)
You also need to initialize the Admin SDK exactly once before you use it:
admin.initializeApp();

How to fix TypeError when using signInWithCredential on node.js? [EDIT: bug in Firebase 6.2.2]

I am trying to sign in to firebase using a Google Id Token, as I'm developing an app that will be running on a raspberry pi, but when trying to sign in using the received token firebase crashes when using signInWithCredential. Here's my minimal reproducible example
var firebase = require("firebase/app");
require("firebase/auth");
const firebaseConfig = {
...
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const id_token = "A_GOOGLE_ID_TOKEN";
var credential = firebase.auth.GoogleAuthProvider.credential(id_token);
firebase.auth().signInWithCredential(credential);
and it crashes with
TypeError: this.f is not a constructor
at ai.a (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:188:361)
at yh (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:171:191)
at bi.o (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:193:175)
at ji (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:191:239)
at C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:197:181
at new C (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:18:736)
at pi (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:197:161)
at C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:209:203
at e.g (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:22:101)
at Kb (C:\Dev\Crashing\node_modules\#firebase\auth\dist\auth.js:25:195)
I tried it with several valid ID Tokens, but it seems that part is actually not broken, the credential itself appears to be fine, because signInWithCredential dies the same way even when I pass an arbitrary string as the id_token.
What am I doing wrong? Or could it possibly be an issue with Firebase JS SDK itself?
I am working on Windows 10, ver. 1809, running Node v10.15.3 and firebase JS SDK 6.2.2 (npm firebase package).
EDIT: I tried Firebase JS SDK version 6.2.0 and the code worked as expected! There is a bug in version 6.2.2 though.
Firebase JS SDK 6.2.3 was just released today, and it fixes this bug:
https://firebase.google.com/support/release-notes/js#authentication
Look like this is the git commit that fixes it:
https://github.com/firebase/firebase-js-sdk/commit/728f4f54b4589c07a2d474deb94328a332c8fe39
I verified it with this mocha unit test:
const firebase = require('../../firebaseApp')
const chai = require('chai')
describe('firebase javascript sdk', () => {
// This unit test verifies that the error message is as expected,
// and not the error "this.f is not a constructor", which was caused
// by a bug in version 6.2.1, and fixed in versin 6.2.3.
// https://stackoverflow.com/questions/56716255/how-to-fix-typeerror-when-using-signinwithcredential-on-node-js-edit-bug-in-f
it('should be able to checkActionCode', () => {
return firebase.auth().checkActionCode('xyz')
.catch(error => {
// https://stackoverflow.com/questions/56716255/how-to-fix-typeerror-when-using-signinwithcredential-on-node-js-edit-bug-in-f
chai.assert.equal(error.message,
"The action code is invalid. This can happen if the code is malformed, expired, or has already been used.")
})
})
})
The Firebase client SDKs generally do not work with nodejs. Firebase Authentication depends heavily on running inside a web browser in order to work correctly.
If you're running node, you might want to consider just using the Firebase Admin SDK to access your project without having to sign in.

Lambda functions to query the GraphQL endpoint?

How can I use Lambda functions to query the GraphQL endpoint (AppSync) in Node.js? Which GraphQL Client should I use?
I have seen AWS AppSync JavaScript SDK which seems to be for mobile app or react/frontend.
PS: I am not talking about AWS Lambda Resolvers.
We use a simple https package to query graphql. You might need to form all the graphql queries manually in that case. If you want to use deal with automated discovery and query with objects you can apollo-fetch clients. Simple CURL works too.
All of the methods are mentioned in detail here.
https://blog.apollographql.com/4-simple-ways-to-call-a-graphql-api-a6807bcdb355
Hope it helps.
If you use AWS_IAM or AMAZON_COGNITO_USER_POOLS as the authentication type, I think AWS AppSync JavaScript SDK is a big help, you just need to set up your code as explained here:
"use strict";
/**
* This shows how to use standard Apollo client on Node.js
*/
global.WebSocket = require('ws');
require('es6-promise').polyfill();
require('isomorphic-fetch');
// Require exports file with endpoint and auth info
const aws_exports = require('./aws-exports').default;
// Require AppSync module
const AUTH_TYPE = require('aws-appsync/lib/link/auth-link').AUTH_TYPE;
const AWSAppSyncClient = require('aws-appsync').default;
...
Also, you must provide credentials
const AWS = require('aws-sdk');
AWS.config.update({
region: aws_exports.REGION,
credentials: new AWS.Credentials({
accessKeyId: aws_exports.AWS_ACCESS_KEY_ID,
secretAccessKey: aws_exports.AWS_SECRET_ACCESS_KEY
})
});
const credentials = AWS.config.credentials;
or just retrieve Lambda session credentials (don't forget to give permission to Lambda execute GraphQL API).

Call a lambda from another Lambda all locally within Serverless

I am using serveless + aws + node.js.
I have a lambda calling another lambda. I can't get to run the lot locally.
I can invoke both lambdas locally with 'serverless invoke local -f ...' BUT
the caller one comes back with:
{"message":"Function not found: arn:aws:lambda:eu-west-1:5701xxxxxxxxxx:function:the-right-function-name"}
as if the caller function invoked the callee on AWS and not locally.
Is there anyway to do stay local and if yes, what may I be missing?
You can achieve that with this plugin. There is a feature of AWS SDK for Lambda that allows you to override the API endpoint of Lambda service. Therefore you can set it to localhost.
const AWS = require('aws-sdk');
const endpoint = process.env.SERVERLESS_SIMULATE ?
process.env.SERVERLESS_SIMULATE_LAMBDA_ENDPOINT :
undefined
const lambda = new AWS.Lambda({ endpoint })
For more details, refer to the plugin's readme. Also there is a nice article about that.

Resources