Async await problem in nodejs sequelize connection string - javascript

function credential(secretFromVault) {
const creddetails = new ClientSecretCredential(clientId, tenantId, cleintSecret);
// Build the URL to reach your key vault
const url = `https://<vaultName>.vault.azure.net/`;
// Lastly, create our secrets client and connect to the service
const client = new SecretClient(url, creddetails);
const secretName = secretFromVault;
return new Promise(resolve => {
client.getSecret(secretName).then(latestSecret => {
console.log(`value from secret is`, latestSecret.value);
resolve(latestSecret.value)
})
})
}
const dbUserName = credential(constants.pgDbUserName)
const dbPassword = credential(constants.pgDbPassword)
const hostname = constants.pgHostname;
const port = constants.pgPort;
const dbName = constants.pgDbName;
const sequelize = new Sequelize(dbName, dbUserName, dbPassword, {
host: hostname,
port: port,
dialect: constants.dialectName,
logging: false,
pool: {
max: constants.pgMaxPoolConnections,
min: constants.pgMinPoolConnections,
acquire: constants.pgMakeConnectionTimeOut,
idle: constants.pgIdleTimeout
}
});
sequelize.authenticate()
.then(() => {
console.log('Successfully connected.');
User.sync();
Credentials.sync();
App.sync();
Entity.sync();
EntityField.sync();
Relationship.sync();
})
.catch(err => console.log('Error: ' + err))
I am using the above code to make connection to postgres database. But I am receiving below error on execution of node index command, index.js is not attached here.
I want dbUSerName and dbUserpassword values to be passed in the sequelize connection string after fetched from the vault. but the values are promise which I am not able to resolve.
error: uncaughtException: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Promise

credential function returns Promise, you need to call it as a promise function.
You can read about promises here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
I think it will be better to wrap your code in a async function and use await before calling credential
async function main() {
const dbUserName = await credential(constants.pgDbUserName);
const dbPassword = await credential(constants.pgDbPassword);
// Your code
}
main();

Related

Async Mongo DB Query

In my code, I am sending a query to my Mongo database. The method findUser() shall return the response of this query. The query works fine, tested with console.log(users).
The problem is the function returns null, it doesn't wait till the query got a response to return the var foundUser.
How could I use await/async in this case in order to wait for the query response before returning anything ?
function findUser(username) {
foundUser = null
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology : true});
client.connect(err => {
const collection = client.db("YourCV").collection("Accounts");
result = collection.findOne({username : username }, function(err, user) {
console.log(user)
if(user){
foundUser = user
}
});
});
return foundUser
};
console.log(user) outputs :
{
_id: 601695084b28102500ae0015,
username: 'jetlime',
password: '$2b$10$EN5k/YKOMBgibqy62s0hGOX9MffHZtXkfsw0Du0j8QVS7mGab5FLi'
}
Many thanks
Update the code to the following:
async function findUser(username) {
const client = await MongoClient.connect(url, { useNewUrlParser: true })
.catch(err => { console.log(err); });
if (!client) {
return;
}
const collection = client.db("YourCV").collection("Accounts");
const user = await collection.findOne({username : username });
client.close(); // -> To be under finally clause.
return user;
};
And call the function with await findUser(username);
Caution: The above of connecting to DB is not recommended. You are establishing a DB connection for every function call. This quickly leads to running out of connections on the DB side when you have a large number of requests.
Move the DB connection establishing part to a commonplace and re-use the connection.
See whatever you do, any operation you perform with your database, it returns promise, so write async keyword before the name of your function in line 1 and then await keyword before your query in line 6, it will then behave like synchronous call and every line will execute accordingly
As you said, you need to use async/await operators for asynchron methods.
You have two choices:
1)Implement callback method on findUser
async function findUser(username, onUsersReady) {
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).connect();
const collection = await client.db("YourCV").collection("Accounts");
await collection.findOne({
username: username
}, function(err, user) {
console.log(user)
if (user) {
foundUser = user
onUsersReady(user);
}
});
};
2)Use function to return results directly
async function findUser(username) {
const client = await new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
}).connect();
const collection = await client.db("YourCV").collection("Accounts");
const foundUser = await collection.findOne({
username
});
return foundUser;
}

JS mysql query result

I'm quite new in Node JS and I'm trying use a mysql DB.
I have try different thing like using promise to get the result of my query but the await is skip and the promise is pending.
I'm kinda lost if someone can explain me how it works.
import * as CMD from "../command/importCommand.js";
export class Message {
constructor(bot, database) {
this.bot = bot;
this.db = database;
}
eventHandler(msg) {
const guild = msg.guild;
const prefix = this.db.getPrefixFromGuild(guild);
console.log(prefix);
//
//
}
}
import * as mysql from "mysql";
export class Database {
constructor() {
this.db = new mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
this.db.connect(err => {
if (err) throw err;
console.log('DB connected');
});
}
async getPrefixFromGuild(guild) {
let prefix = await this.getPrefixFromGuildId(guild.id);
return prefix;
}
async getPrefixFromGuildId(guildId) {
let prefix = await this.query("select prefix from serveur where id_serveur=" + guildId + ";");
return prefix;
}
query(sql) {
return this.db.query(sql, (err, rows) => {
if (err)
throw err;
console.log(rows);
return rows;
});
}
}
Your eventHandler is not an async function and does not await the promise returned from getPrefixFromGuild(). The console.log() statement just logs the promise, not its result. Try this:
async eventHandler(msg) {
const guild = msg.guild;
const prefix = await this.db.getPrefixFromGuild(guild);
console.log(prefix);
}
Please also note that if you access an instance of your Database class right after creation, it might not be initialized since the constructor ist not waiting for the conntect() to complet (it shouldn't but you should find another way to prevent access to an uninitialized Database object).

slack bot sending direct message to user using aws lambda function

I'm trying to send a direct message using slack web api to a user but I think my getSlackUser method which gets all the available users does not complete in time for when I call slackId;
the console.log(slackId) gives undefined meaning it doesn't complete my api call with bolt
how do I ensure getSlackUser method finishes (make it blocking) before it moves on to the rest?
const { WebClient } = require('#slack/web-api');
const { App } = require('#slack/bolt')
const rtm = new RTMClient(process.env.SLACK_OAUTH_TOKEN);
const web = new WebClient(process.env.SLACK_OAUTH_TOKEN);
const app = new App({
token: process.env.SLACK_OAUTH_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
exports.handler = async (event) => {
const slackId = await getSlackUser('example_real_name').id;
console.log(slackId);
await sendSlackMessage(slackId, 'Bot message');
}
sendSlackMessage = async (channel, message) => {
await web.chat.postMessage({
channel: channel,
text: message,
as_user: true
});
}
getSlackUser = async(real_name) => {
const result = await app.client.users.list({
token: process.env.SLACK_OAUTH_TOKEN
});
console.log(result);
return result.members.find((user) => user.real_name == real_name);
}
The problem is precedence on this line:
const slackId = await getSlackUser('example_real_name').id;
Since member access has a higher precedence (evaluated before) than await, it is effectively the same as:
const slackId = await (getSlackUser('example_real_name').id);
getSlackUser returns a Promise object, then its id member is undefined. Await waits for the undefined, which is undefined.
To fix this, make sure that the await is evaluated before the .id:
const slackId = (await getSlackUser('example_real_name')).id;

By using ledger nano s, I wanna sign a transaction and send it

I'm trying to send ethereum transaction that sends ERC20 tokens to someone with Ledger Nano S through Node.JS but I'm not able to successfully sign and send this transaction.
First of all, I signed the transaction through the method, signTransaction, of ledgerhq API and then after signing it, I sended it to the main net by using sendSignedTransaction. When I execute below code, Ledger receives request and shows details of a transaction. However, after pressing Ledger's confirm button, the console returns error 'Returned error: Invalid signature: Crypto error (Invalid EC signature)'.
import AppEth from "#ledgerhq/hw-app-eth";
import TransportU2F from "#ledgerhq/hw-transport-u2f";
import TransportNodeHid from "#ledgerhq/hw-transport-node-hid";
import EthereumTx from "ethereumjs-tx"
const Web3 = require('web3');
import { addHexPrefix, bufferToHex, toBuffer } from 'ethereumjs-util';
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
var destAddresses = ['0xa6acFa18468786473269Dc1521fd4ff40F6481D9'];
var amount = 1000000000000;
var i=0;
var contract = new web3.eth.Contract([token contract ABI... ], '0x74a...');
const data1 = contract.methods.transfer(destAddresses[0], amount).encodeABI();
const exParams = {
gasLimit: 6e6,
gasPrice: 3e9,
from: '0x1A...',
data : data1,
to: '0x74a...',
value: '0x00',
nonce: "0x0",
chainId: 1,
v: "0x01",
r: "0x00",
s: "0x00"
}
async function makeSign(txParams) {
const tx = new EthereumTx(txParams);
const txHex = tx.serialize().toString("hex");
const signedTransaction = '0x' + txHex;
let transport;
try {
transport = await TransportNodeHid.create();
let eth2 = new AppEth(transport);
const result = await eth2.signTransaction("m/44'/60'/0'/0", txHex).then(result => {
web3.eth.sendSignedTransaction('0x' + txHex)
.then(res => {
console.log(res);
}).catch(err => {
console.log('sendSignedTransaction');
console.log(err);
});
}).catch(err => {
console.log('signTransaction');
console.log(err);
});
txParams.r = `0x${result.r, 'hex'}`;
txParams.s = `0x${result.s, 'hex'}`;
txParams.v = `0x${result.v, 'hex'}`;
return result;
} catch (e) {
console.log(e);
}
}
makeSign(exParams).then(function () {
console.log("Promise Resolved2");
}.catch(function () {
console.log("Promise Rejected2");
});
When I only use signTransaction function, I can confirm the transaction in the ledger device and return txhash on the console. However, ultimately I want to broadcast a transaction to the main net. Could you please give me any idea? I want any feedback. Also, if there are any examples of creating and broadcasting a raw transaction by using the ledger, notice me please.
Your code already sends the transaction to the network. However, just awaiting the "send" promise only gives you the transaction hash, not the receipt. You need to treat it as an event emitter and wait for the 'confirmation' event.
const serializedTx = tx.serialize();
web3.eth.sendSignedTransaction(serializedTx.toString('hex'))
.once('transactionHash', hash => console.log('Tx hash', hash))
.on('confirmation', (confNumber, receipt) => {
console.log(`Confirmation #${confNumber}`, receipt);
})
.on('error', console.error);
To send it to mainnet as you mention, you can either run a local geth node on port 8545 and use your code unchanged, or point web3 at infura or similar.

Node express app calling mssql is saying that Connection is closed

I have another app which uses express and routes but this new app i was slimming it down. I know the connection string stuff is correct
script.getQuestions(connection);
script.getQuestions = function(connection,req, res){
console.log(connection);
}
I have read that some people said online to change to use a promise for async fixes this... problem is that with my function having req and res i don't know how to pass those in when i even try to refactor with a promise
"ConnectionError: Connection is closed"
"(module.js:487:32) code: 'ECONNCLOSED', name: 'ConnectionError' }"
What I call up (script) is
var sql = require('mssql');
exports.getQuestions = function(connection, req,res){
console.log(connection);
var request = new sql.Request(connection);
var query = 'select * from Question'
request.query(query).then(function(resultset){
res.json(resultset.recordset);
}).catch(function(err){
console.log(err);
//res.json(err)
})
}
it's a bit hard to understand what you're doing there. But here is an promise example to use mssql
const sql = require('mssql')
sql.connect(config).then(pool => {
// Query
return pool.request()
.input('input_parameter', sql.Int, value)
.query('select * from mytable where id = #input_parameter')
}).then(result => {
console.dir(result)
// Stored procedure
return pool.request()
.input('input_parameter', sql.Int, value)
.output('output_parameter', sql.VarChar(50))
.execute('procedure_name')
}).then(result => {
console.dir(result)
}).catch(err => {
// ... error checks
})
sql.on('error', err => {
// ... error handler
})
source: https://www.npmjs.com/package/mssql#promises

Categories

Resources