Nodejs stream with braintree? - node.js

I am trying to build an api route for a transaction, I want to grab the transaction details from the braintree server.
My app is setup so that the braintree customerId() is the same as the ID as my app user. So below I search for all the transactions for a particular user logged in.
Meaning req.user.id will always equal customerId() which sits on the braintree server.
app.get('/project', function(req, res) {
if(req.user) {
// Finds all transactions for a particular customer
var stream = gateway.transaction.search(function (search) {
search.customerId().is(req.user.id);
});
console.log(stream);
//res.send(stream);
}
});
I want to return the details, but the stream looks like below. So obviously this makes me think that there is a certain way to handle a node stream?
I have seen things like readable-stream, I am not sure if that is what I need to handle this stream object.
My question is how do I handle the stream object to return the details of the transaction?
{ _readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: false,
calledRead: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
objectMode: true,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events: {},
_maxListeners: 10,
searchResponse: { stream: [Circular], success: true },
currentItem: 0,
currentOffset: 0,
bufferedResults: [] }

This returned the transaction data. I am going to keep looking into node streams, and am open to making this better, but as of now it at least returns the data.
stream.on("data", function (data) {
res.json(data);
});
This gives me an error though Error: Can't set headers after they are sent.

I think stream.pipe(res) should work.
The reason you were getting that "can't set headers after they are sent" error, is because the streams 'data' event was emitted multiple times, so you were trying to call res.json multiple times for the same request.

Related

How do i get a file from a writable node stream?

What am i doing
So I'm trying to reply to a command interaction with a QR code, and I don't want to save the file to the directory of the bot and then send it that way, instead, I have the QR code text, and I'm using the QR Code package to convert it into a QR Code, and now I'm trying to write the file to a node stream.
What is the problem
The problem is I don't know how to access that file, since when I try to use { files: [returned.qrcode] } it doesn't send an image attachment.
More information
Its a writable stream, dont know how to get the file from the stream, it returns a normal writable stream
The code
The code for getting the QR Code and writing it to a stream
const id = uuid.v4();
const temp_secret = speakeasy.generateSecret({
name: "VikkiVuk (2FA): " + id
});
let newUser = await new factorschema({
id: id,
temp_secret: temp_secret.base32,
secret: "waiting"
}).save()
await schema.updateOne({ userid: user.id }, { uuid: id })
let data
const filestream = new Stream.Writable()
qrcode.toFileStream(filestream, temp_secret.otpauth_url)
const readableStream = new Stream.Readable()
readableStream.push(null)
readableStream.pipe(filestream)
filestream.end()
return { userid: id, temp_secret: temp_secret, qrcode: readableStream }
Command code (the part where I try and send the attachment)
await interaction.deferReply({ ephemeral: true })
const result = await handler.register2FA(interaction.user)
console.log(result) // logs a stream, its not undefined
await interaction.editReply({ content: "Scan this qr code", ephemeral: true, files: [result.qrcode]})
Logged stream:
Readable {
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: [ [Writable] ],
flowing: true,
ended: true,
endEmitted: false,
reading: false,
constructed: true,
sync: true,
needReadable: false,
emittedReadable: true,
readableListening: false,
resumeScheduled: true,
errorEmitted: false,
emitClose: true,
autoDestroy: true,
destroyed: false,
errored: null,
closed: false,
closeEmitted: false,
defaultEncoding: 'utf8',
awaitDrainWriters: null,
multiAwaitDrain: false,
readingMore: false,
decoder: null,
encoding: null,
[Symbol(kPaused)]: false
},
_events: [Object: null prototype] {
end: [Function: bound onceWrapper] { listener: [Function: onend] },
data: [Function: ondata]
},
_eventsCount: 2,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}
Firstly, transform your stream like so:
async function createStream() {
const stream = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk)
callback()
}
})
await qrcode.toFileStream(filestream, temp_secret.otpauth_url)
}
return stream;
The MessageAttachment constructor available to discord.js accepts writeable streams you may convert your stream to a .png using the constructor like so:
const {
MessageAttachment
} = require("discord.js");
let qrcode = createStream();
const x = new MessageAttachment(qrcode, 'QRCode.png') // further attach it like so:
await interaction.editReply({
content: "Skeniraj ovaj qr code dole.",
ephemeral: true,
files: [x]
})
Constructor accepts the following three parameters, Where attachment would be your writable stream , name would be your filename and data would be the APIAttachment object which also offers you options such as width and height of that image / specifics listed in the documentation.

How to consume the node stream returned by braintree

Braintree provides an api to search for the transactions. Braintree has provided an example, but i'm not aware how to read the node stream returned by braintree. Please look into the following code snippet:
var stream = gateway.transaction.search(function (search) {
search.paymentMethodToken().is("h337xg");
});
stream.pipe(someWritableStream);
//When I try to print the stream in console, I get the following result:
{
_readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: false,
calledRead: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
objectMode: true,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events: {},
_maxListeners: 10,
searchResponse: { stream: [Circular], success: true },
currentItem: 0,
currentOffset: 0,
bufferedResults: []
}
From nodejs stream documentation
http://nodejs.org/api/stream.html#apicontent
A stream is an abstract interface implemented by various objects in Node. For >example a request to an HTTP server is a stream, as is stdout. Streams are >readable, writable, or both. All streams are instances of EventEmitter
You should make use of stream's data event to capture data as it is being received by the stream. The stream's end event is called when complete data is received from the steam
completeData = ""
someWritableStream.on("data", function(chunk){
//Do Something With the chunk of data. You might want to concat the stream
completeData += chunk;
});
someWritableStream.on("end", function(){
//Do Something after the all the chunks are received.
console.log(completeData);
});

Nodejs request socket object parameter

Sorry if I ask silly question, I am working with the example below regarding on nodejs long polling.
http://www.stoimen.com/blog/2010/12/02/diving-into-node-js-a-long-polling-example/
I understand most of them, but just one thing I am not quite able to understand although I have done thousands of searching.
fs.stat('filepath', function(err, stats) {
// if the file is changed
if (stats.mtime.getTime() > request.socket._idleStart.getTime()) {
// read it
fs.readFile('filepath', 'utf8', function(err, data) {
// return the contents
response.writeHead(200, {
'Content-Type' : 'text/plain',
'Access-Control-Allow-Origin' : '*'
});
// return response
response.write(data, 'utf8');
response.end();
// return
return false;
});
}
});
The part "request.socket._idleStart", what is the meaning of the parameter _idleStart? Actually, I try to print out the whole request object and got the following parameters.
_readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: false,
calledRead: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
objectMode: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events: {},
_maxListeners: 10,
socket:
....
...
...
I am wondering if there is any documentations describing these parameters, thanks for all for the help!
those parameters with _ underscore, are used for maintaining the state of socket, its not meant for working with them. there are functions that are more reliable than those.
from node.js documentation
readable._read
Note: This function should NOT be called directly. It should be
implemented by child classes, and called by the internal Readable
class methods only.
All Readable stream implementations must provide a _read method to
fetch data from the underlying resource.
This method is prefixed with an underscore because it is internal to
the class that defines it, and should not be called directly by user
programs. However, you are expected to override this method in your
own extension classes.

How do I store a mongojs query result to a variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
All i get from this code:
var views = db.books.find({"number":1}, {"views":1, _id:0});
console.log(views);
is this response:
{ _readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: false,
calledRead: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
objectMode: true,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
domain: null,
_events: {},
_maxListeners: 10,
_get: [Function] }
You can use .findOne to return a single instance and get the result.
Find assumes you're querying for a collection of documents and return a cursor:
You can for example, convert it to an array:
db.books.find({"number":1}, {"views":1, _id:0}).toArray(function(err, results){
console.log(results);
});
You can use .each to iterate through elements and .nextObject to get the next, they're all asynchronous obviously being IO operations in nodejs, here is the section on cursors in the manual.

MongoJS: size() method or length not available

I just installed the latest versions of node.js and MongoDB and a driver for node.js: MongoJS
Now I tried to find out (with good performance due a high load app) if a record exists in the database. I tried this query but all I get is an error:
var query = db.users.find({ nickname: 'test' }).limit(1);
console.log(query.size());
// or also
// console.log(query.length);
// => undefinied
Error:
TypeError: Object [object Object] has no method 'size'
Via console.log(typeof query) I just get object.
If I just log query I get this:
{ _readableState:
{ highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: false,
ended: false,
endEmitted: false,
reading: false,
calledRead: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
objectMode: true,
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: null }
readable: true,
domain: null,
_events: {},
_maxListeners: 10,
_get: [Function] }
I get all the time this as result, even if the item exists or not.
I don't see any mention of a size method in the current docs. Instead, while count would also work here, you could use findOne to do this:
db.users.findOne({ nickname: 'test' }, function(err, doc) {
if (doc) {
// At least one matching doc exists
} else {
// No match found
}
});

Resources