Firebase Async/Await DeprecationWarning: Unhandled promise rejections are deprecated - firebase

I am trying to create a simple connection to my Firebase Realtime-Database using Functions with Async/Await to reduce code and even thou I wrap the code using try/catch, it still throws the following error.
exports.createBlogPost = functions.https.onRequest(async (req, res) => {
try {
cors(req, res, () => { });
const response = req.body;
response.createDate = new Date();
const snapshot = await admin.database().ref(BLOG_POSTS).push(response);
console.log("SNAP", snapshot.getKey());
response.id = snapshot.getKey();
res.send(response);
} catch (e) {
res.status(500).send(e);
}
});
It creates the instance in the database but I receive the following warning:
info: SNAP -LdnpewpwEz9EOkAA05H
error: (node:13656) UnhandledPromiseRejec: Unhandled promise rejections are deprecated.
In the future, promise rejectiontionWarning: Unhandled promise rejection. Node.js process with a non-zero exit code.
This error originated either by throwingon completed successfully inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)(node:13656)
[DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.info: Execution took 1035 ms, user function completed successfullyerror: Function worker killed by signal: SIGTERM

Related

solc inside firebase functions causes deployment error

I need to compile a smart contract inside a firebase function. I am using solc "solc": "^0.8.13", in my package.json.
Code of the firebase function responsible to create the contact is;
const functions = require("firebase-functions");
const admin = require('firebase-admin');
const solc = require('solc');
const fs = require("fs");
const Web3 = require('web3');
exports.createSC = functions.https.onCall((data, context) => {
if (!context.auth) return { data: data, status: 'error', code: 401, message: 'Not signed in' }
return new Promise((resolve, reject) => {
admin.auth().getUser(data.owner)
.then(userRecord => {
//below function compiles the contract and returns abi/binary code etc
let contract = instantiateContract('sources/SnaphashToken.sol');
//use web3 to actually deploy contract
let web3;
//...code emitted...
resolve(contractDeployResult)
})
.catch(error => {
console.error('Error fetching user data:', error)
reject({ status: 'error', code: 500, error })
})
});
})
this works perfectly well when deployed on functions simulator locally but when deployed on firebase cloud I get this exception;
i functions: updating Node.js 16 function ethereum-createSC(us-central1)...
Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation.
Functions deploy had errors with the following functions:
ethereum-createSC(us-central1)
When I comment out const solc = require('solc') in my function, it deploys without problems. I really need to be able to deploy smart contracts after modifying based on user input and would appreciate a help on it
I found out that the subject function was causing deployment error because of Error: memory limit exceeded. I was able to see that after I checked detailed logs of the functions with firebase functions:log
2022-05-27T17:09:27.384860094Z E ethereum-createNft: Function cannot be initialized. Error: memory limit exceeded.
In order to fix this issue, I increased memory for the function from default 256MB to 1GB and timeoutSeconds from default 60 seconds to 120 seconds
exports.createNft = functions.runWith({memory:'1GB',timeoutSeconds:120}).https.onCall((data, context) => {
..code here..
});
And then deployment was successful

Deploying next-auth app to Vercel creates error in credentials provider

I am trying to deploy my next app to vercel. I am using next-auth for authentication with credentials and an api that returns a JWT. On localhost it works ok, but when I put it on vercel, and try to login, nothing happens. However when I view the logs in the project's dashboard functions, there's an error:
[POST] /api/auth/callback/credentials
03:32:18:58
2021-12-21T00:32:19.071Z 410db3c3-d841-45d1-8df2-0cdbb4aa8793 ERROR TypeError: "ikm"" must be an instance of Uint8Array or a string
at normalizeUint8Array (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:20:15)
at normalizeIkm (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:24:17)
at hkdf (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:47:60)
at getDerivedEncryptionKey (/var/task/node_modules/next-auth/jwt/index.js:99:34)
at Object.encode (/var/task/node_modules/next-auth/jwt/index.js:45:34)
at Object.callback (/var/task/node_modules/next-auth/core/routes/callback.js:457:37)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async NextAuthHandler (/var/task/node_modules/next-auth/core/index.js:197:28)
at async NextAuthNextHandler (/var/task/node_modules/next-auth/next/index.js:40:7)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils.js:101:9)
2021-12-21T00:32:19.071Z 410db3c3-d841-45d1-8df2-0cdbb4aa8793 ERROR TypeError: "ikm"" must be an instance of Uint8Array or a string
at normalizeUint8Array (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:20:15)
at normalizeIkm (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:24:17)
at hkdf (/var/task/node_modules/#panva/hkdf/dist/node/cjs/index.js:47:60)
at getDerivedEncryptionKey (/var/task/node_modules/next-auth/jwt/index.js:99:34)
at Object.encode (/var/task/node_modules/next-auth/jwt/index.js:45:34)
at Object.callback (/var/task/node_modules/next-auth/core/routes/callback.js:457:37)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async NextAuthHandler (/var/task/node_modules/next-auth/core/index.js:197:28)
at async NextAuthNextHandler (/var/task/node_modules/next-auth/next/index.js:40:7)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils.js:101:9)
RequestId: 410db3c3-d841-45d1-8df2-0cdbb4aa8793 Error: Runtime exited with error: exit status 1
Runtime.ExitError
Additional info:
The SignIn() function looks like this:
signIn("credentials", {
email: values.name,
password: values.password,
redirect: false,
callbackUrl: `/app`
})
.then((data) => console.log("loginpagethen", data))
.catch((error) => console.log("loginpagecatch", error));
I think the problem occurs somewhere in the jwt callback function because authorize returns a user(with all the data, including jwt from server). Also if I console.log the user in the jwt callback function,I can actually see the user object. However the session isn't present.
async jwt({ token, user, account, profile, isNewUser }) {
if (user) {
console.log("user", user); //user is there
token.accessToken = user.token;
}
return token;
},
async session(session, token) {
console.log("session", session); //session is not there
return session;
},
};
P.S. I have added environment variables.
Any idea on how I can get my app to behave on vercel?
in your .env file creates an environment variable:
API_SECRET_KEY=q3t6w9z$C&F)asdfasdfasfasdfasdfasd1sdfasf

Does firebase transaction retry run codes beyond the transaction?

If there are more codes/logic outside the transaction that should only be run when the transaction succeeds, will these codes be ran after the retry succeed? See construed example below based on my Express route handler.
app.post('/some/path/to/endpoint', async (req, res) => {
try {
await db.runTransaction(async t => {
const snapshot = t.get(someDocRef);
const data = snapshot.data();
doSomething(snapshot);
return t.update(snapshot.ref, { someChanges });
});
// QUESTION: If transaction retries and succeeds, will the below code run once?
// logic that requires the transaction succeeds
await axios.post(url, data);
res.status(200).send('success');
} catch (e) {
res.status(500).send('system error');
}
});
Appreciate expert views on this. Thanks
You can find the documentation for runTransaction here.
As you can see, runTransaction() returns a Promise. When you await a Promise, and with you code inserted in a try/catch block, if an error is thrown everything after will be ignored, because the flow will go in the catch statement.
So the answer is yes: everything after runTransaction(), the way you wrote it, will not be executed if something goes wrong.

Failed to load resource: the server responded with a status of 500 () when using firebase cloud functions to access cloud firestore

I know that there are similar posts about this, but I tried all of them and non worked.
I wrote this function for getting the user's name from the UID. I have a collection called users, with each user's uid as the name of the document, and a value called displayName in it.
exports.getDisplayName = functions.https.onCall((data, context) => {
if(context.auth){
const uid = data.uid
return admin.database().ref(`/users/${uid}`).get().then(doc=>{return{name: doc.data().displayName}})
}else{
throw new functions.https.HttpsError('failed-precondition', 'The function must be called while authenticated.');
}
})
When it deploy it everything works fine but when I call it I get these 2 errors and I can't figure out how to solve it.
Failed to load resource: the server responded with a status of 500 ()
Unhandled Promise Rejection: Error: INTERNAL
I have another function that works fine:
exports.getUidFromEmail = functions.https.onCall((data, context) => {
if(context.auth){
const email = data.email
return admin.auth().getUserByEmail(email).then((userRecord)=>{ return {user: userRecord.uid}})
}else{
throw new functions.https.HttpsError('failed-precondition', 'The function must be called while authenticated.');
}
})
edit: the error it says is this:
Unhandled error FirebaseError: Can't determine Firebase Database URL.
at FirebaseDatabaseError.FirebaseError [as constructor] (/workspace/node_modules/firebase-admin/lib/utils/error.js:44:28)
at new FirebaseDatabaseError (/workspace/node_modules/firebase-admin/lib/utils/error.js:205:23)
at DatabaseService.ensureUrl (/workspace/node_modules/firebase-admin/lib/database/database-internal.js:97:15)
at DatabaseService.getDatabase (/workspace/node_modules/firebase-admin/lib/database/database-internal.js:65:26)
at FirebaseApp.database (/workspace/node_modules/firebase-admin/lib/firebase-app.js:228:24)
at FirebaseNamespace.fn (/workspace/node_modules/firebase-admin/lib/firebase-namespace.js:191:45)
at /workspace/index.js:17:22
at func (/workspace/node_modules/firebase-functions/lib/providers/https.js:273:32)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
errorInfo: {
code: 'database/invalid-argument',
message: "Can't determine Firebase Database URL."
}
}
Solved my issue. It was because I was using Cloud Firestore instead of Realtime database, because a lot of the examples and docs are using it, I thought it just had a different syntax 🤦🏻
here's the fixed code:
exports.getDisplayName = functions.https.onCall((data, context) => {
if(context.auth){
const uid = data.uid
return admin.firestore().collection("users").doc(uid).get().then(doc=>{
console.log(doc)
return{name: doc.data().displayName}
})
}else{
throw new functions.https.HttpsError('failed-precondition', 'The function must be called while authenticated.');
}
})
it's admin.firestore() not admin.database()

Jest - TypeError: Network request failed for fetch

Im using Jest to test a REST API and I'm receiving TypeError: Network request failed responses whenever I issue a fetch request. All of the calls to the REST API work on the application and fail exclusively on my Jest tests.
Are there any known incompatibilities between fetch and Jest? For example this simple test ends up executing the catch statement:
it('should find a result via fetch', () => {
fetch('http://www.google.com').then(() => console.log('Success')).catch((err) => console.log('Error!!!!' + err));
});
The result received is: Error!!!!TypeError: Network request failed
You need to return the Promise that fetch returns:
it('should find a result via fetch', () => {
return fetch('http://www.google.com')
.then(() => console.log('Success'))
.catch((err) => console.log('Error!!!!' + err));
});
You can read more in the jest docs about async testing here: https://facebook.github.io/jest/docs/tutorial-async.html
Additionally, using jest in create-react-app will use the whatwg-fetch polyfill via jsdom. You can force the use of isomorphic-fetch by importing it directly:
import fetch from 'isomorphic-fetch';
Ok I've gotten this to work using async await, but I still don't understand why it doesn't work without an async block- So right now my test works with this code:
it('should find a result via REST', async () => {
const data = await CqApi.personSearch('XYZ');
expect(....).toBeDefined();
});

Resources