-
Notifications
You must be signed in to change notification settings - Fork 3
Description
At the moment:
exportis an async method that takes one string param and returns a promise that resolves to a readable stream. Callers can then encode it to csv by piping the returned stream to a writable csv encoder stream.importis an async method that takes several params, including a readable stream, and returns a promise (no resolved value applicable). CSV decoding happens within the method.compareis an async method that takes two string params and returns a promise that resolves to an array of objectsmergeis an async method that takes a few string params and returns a promise (no resolved value applicable)
The main issue I have is with where csv encoding/decoding happens (it's different in import vs export). I'm thinking it should always happen outside (at the server/cli level) and the methods should just deal with object streams.
But moving csv decoding to the server is a bit tricky because of the way we pass the readable stream to the import method, as an argument. The method then calls a couple async functions, and then attaches the .on('data') and .on('error') handlers.
The trouble is that the flow is activated back in server when we { data: req.body.pipe(csvParser()) }, and the error handler isn't attached until after some async functions, so early errors are missed. Normally a stream interface would look something like
const importStream = await gitSheets.import(opts)
req.body.pipe(csvParser()).pipe(importStream)So that means the import method should probably take the opts and return a writable stream.
And while we're at it, compare may as well return a readable stream of the diffs since that's what export does. The combination of promises and streams can be a bit confusing, but the alternative of just dealing with promises and not streams makes us less equipped to deal with large CSV files (though maybe it's premature optimisation).