diff --git a/lib/www/server/api/middleware/event/list/csv.js b/lib/www/server/api/middleware/event/list/csv.js new file mode 100644 index 0000000..e083084 --- /dev/null +++ b/lib/www/server/api/middleware/event/list/csv.js @@ -0,0 +1,83 @@ +const { stringify } = require('csv'); +const { event } = require('../../../../lib/db'); +const { ALERT, ERROR, INFO, DEBUG } = require('DOUGAL_ROOT/debug')(__filename); + +const csv = async function (req, res, next) { + try { + const events = await event.list(req.params.project, req.query); + if ("download" in req.query || "d" in req.query) { + const extension = "csv"; + const tstamp = (new Date()).toISOString(); + const filename = `${req.params.project}-event-log-${tstamp}.${extension}`; + res.set("Content-Disposition", `attachment; filename="${filename}"`); + } + + const columns = { + id: "id", + unix_epoch: (row) => Math.floor(row.tstamp/1000), + timestamp: (row) => (new Date(row.tstamp)).toISOString(), + sequence: "sequence", + point: "point", + text: "remarks", + labels: (row) => row.labels.join(";"), + latitude: (row) => { + if (row.meta.geometry?.type == "Point" && row.meta.geometry?.coordinates) { + return row.meta.geometry.coordinates[1]; + } + }, + longitude: (row) => { + if (row.meta.geometry?.type == "Point" && row.meta.geometry?.coordinates) { + return row.meta.geometry.coordinates[0]; + } + } + }; + + let fields = [ "timestamp", "sequence", "point", "text", "labels", "latitude", "longitude", "id" ]; + + if (req.query.fields) { + fields = req.query.fields.split(/[,;:.\s+*|]+/); + } + + let delimiter = req.query.delimiter ?? ","; + + const stringifier = stringify({delimiter}); + stringifier.on('error', (err) => { + ERROR(err); + }); + + stringifier.on('readable', () => { + while((row = stringifier.read()) !== null) { + res.write(row); + } + }); + + stringifier.on('end', () => { + DEBUG("Transform complete"); + res.end(); + next(); + }); + + res.status(200); + + if (!req.query.header || req.query.header.toLowerCase() == "true" || req.query.header == "1") { + // Send header + stringifier.write(fields); + } + + events.forEach( event => { + stringifier.write(fields.map( field => { + if (typeof columns[field] === "function") { + return columns[field](event); + } else { + return event[columns[field]]; + } + })); + }); + + stringifier.end(); + } catch (err) { + next(err); + } +}; + +module.exports = csv; diff --git a/lib/www/server/api/middleware/event/list/index.js b/lib/www/server/api/middleware/event/list/index.js index c1fa87e..b6d3531 100644 --- a/lib/www/server/api/middleware/event/list/index.js +++ b/lib/www/server/api/middleware/event/list/index.js @@ -1,13 +1,15 @@ const json = require('./json'); const geojson = require('./geojson'); const seis = require('./seis'); +const csv = require('./csv'); module.exports = async function (req, res, next) { try { const handlers = { "application/json": json, "application/geo+json": geojson, - "application/vnd.seis+json": seis + "application/vnd.seis+json": seis, + "text/csv": csv }; const mimetype = (handlers[req.query.mime] && req.query.mime) || req.accepts(Object.keys(handlers));