Comparing version 4.2.0 to 4.3.1
184
lib/index.js
@@ -6,4 +6,6 @@ 'use strict'; | ||
const Async = require('async'); | ||
const XLSX = require('xlsx'); | ||
const ExcelJs = require('exceljs'); | ||
const FastCsv = require('fast-csv'); | ||
const internals = { | ||
@@ -19,3 +21,5 @@ routeMap: new Map() | ||
// Build up routeMap for all routes on all connections | ||
/** | ||
* Build up routeMap for all routes on all connections | ||
*/ | ||
server.ext('onPreStart', (srv, nxt) => { | ||
@@ -36,3 +40,5 @@ | ||
// allow .csv requests | ||
/** | ||
* allow .csv or .xlsx requests | ||
*/ | ||
server.ext('onRequest', (request, reply) => { | ||
@@ -104,14 +110,30 @@ | ||
if (internals.enableExcel && preferredType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') { | ||
const fileName = request.path.substring(request.path.lastIndexOf('/') + 1 || 0, request.path.length); | ||
const xlsx = internals.processSchema(schema, resolvedSchemasObject, request.response.source, options.resultKey, internals.headerQueryMapToExcel); | ||
const excel = XLSX.write(xlsx, { bookType: 'xlsx', bookSST: false, type: 'buffer', compression: true, ...options.excelWriteOptions }); | ||
const response = reply(excel); | ||
return response.encoding('base64').type(`${preferredType}; charset=${response.settings.charset}; header=present;`).header(`'content-disposition', 'attachment'; filename=${fileName}.xlsx;`).header('Content-Length', excel.length); | ||
} | ||
internals.processSchema(schema, resolvedSchemasObject, request.response.source, options.resultKey, (headerQueryMap, dataset) => { | ||
const csv = internals.processSchema(schema, resolvedSchemasObject, request.response.source, options.resultKey, internals.headerQueryMapToCsv); | ||
const res = request.raw.res; | ||
if (internals.enableExcel && preferredType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') { | ||
const wbOptions = { | ||
stream: res, // write to server response | ||
useStyles: false, | ||
useSharedStrings: false | ||
}; | ||
const response = reply(csv); | ||
return response.type(`${preferredType}; charset=${response.settings.charset}; header=present;`).header('content-disposition', 'attachment;'); | ||
const workbook = new ExcelJs.stream.xlsx.WorkbookWriter(wbOptions); | ||
res.setHeader('Content-disposition', 'attachment;'); | ||
res.setHeader('Content-type', `${preferredType};`); | ||
internals.headerQueryMapToExcel(headerQueryMap, dataset, workbook); | ||
} | ||
else { | ||
const csvStream = FastCsv.createWriteStream({headers: true}); | ||
csvStream.pipe(res); | ||
res.setHeader('Content-disposition', 'attachment;'); | ||
res.setHeader('Content-type', `${preferredType};`); | ||
internals.headerQueryMapToCsv(headerQueryMap, dataset, csvStream); | ||
} | ||
}); | ||
}); | ||
@@ -128,2 +150,11 @@ }); | ||
/** | ||
* Take header schema and dataset and prep it for use in csv/xlsx creation | ||
* @param {} schema | ||
* @param {} dynamicSchema | ||
* @param {[]} dataset | ||
* @param {} resultKey | ||
* @param {function (headerQueryMap, dataset)} callback | ||
* @returns {primitiveType | callback} | ||
*/ | ||
internals.processSchema = (schema, dynamicSchemas, dataset, resultKey, callback) => { | ||
@@ -225,3 +256,7 @@ | ||
// Utility function to convert an array to a Map | ||
/** | ||
* Utility function to convert an array to a Map | ||
* @param {[]} array | ||
* @returns {Map} | ||
*/ | ||
internals.arrayToMap = (array) => { | ||
@@ -243,57 +278,67 @@ | ||
internals.headerQueryMapToCsv = (headerQueryMap, dataset) => { | ||
/** | ||
* Push data to a csv stream | ||
* @param {Map} headerQueryMap headers | ||
* @param {[{}]} dataset data | ||
* @param {Stream} csvStream | ||
*/ | ||
internals.headerQueryMapToCsv = (headerQueryMap, dataset, csvStream) => { | ||
let headerRow = ''; | ||
// Generate and set headers row | ||
let headerRow = []; | ||
for (const header of headerQueryMap.keys()) { | ||
headerRow += `${header}${internals.separator}`; | ||
headerRow.push(`${header}`); | ||
} | ||
csvStream.write(headerRow); | ||
let csv = `${headerRow}\n`; | ||
// Push data to stream | ||
internals.generateDataRows(headerQueryMap, dataset, function (dataRow) { | ||
csvStream.write(dataRow); | ||
}); | ||
if (!Array.isArray(dataset)) { | ||
dataset = [dataset]; | ||
} | ||
// End stream | ||
csvStream.end(); | ||
}; | ||
let valueFound = true; | ||
/** | ||
* Push data to a excel workbook stream | ||
* @param {Map} headerQueryMap headers | ||
* @param {[{}]} dataset data | ||
* @param {Stream} csvStream | ||
*/ | ||
internals.headerQueryMapToExcel = (headerQueryMap, dataset, workbook) => { | ||
for (let i = 0; i < dataset.length; ++i) { | ||
let dataRow = ''; | ||
const sheet = workbook.addWorksheet('sheet'); | ||
for (const query of headerQueryMap.values()) { | ||
let temp = dataset[i]; | ||
// Generate and set headers row | ||
const headerRow = []; | ||
for (const header of headerQueryMap.keys()) { | ||
headerRow.push({ | ||
name: header, | ||
header | ||
}); | ||
} | ||
sheet.columns = headerRow; | ||
for (const queryPart of query) { | ||
if (temp[queryPart] === null || temp[queryPart] === undefined) { | ||
valueFound = false; | ||
// Push data to stream | ||
internals.generateDataRows(headerQueryMap, dataset, function (dataRow) { | ||
sheet.addRow(dataRow).commit(); | ||
}); | ||
// We break out of the for loop because there is no need to dig deeper into the object, the object is already undefined or null | ||
break; | ||
} | ||
else { | ||
temp = temp[queryPart]; | ||
} | ||
} | ||
if (!valueFound) { | ||
valueFound = true; | ||
} | ||
else { | ||
temp = internals.dateToISOString(temp); | ||
dataRow += `"${internals.escapeQuotesInString(temp)}"`; | ||
} | ||
dataRow += internals.separator; | ||
} | ||
csv += `${dataRow}\n`; | ||
} | ||
return csv.trim(); | ||
// End stream | ||
sheet.commit(); | ||
workbook.commit(); | ||
}; | ||
internals.headerQueryMapToExcel = (headerQueryMap, dataset) => { | ||
/** | ||
* Generic function that loops through data and generates rows | ||
* These rows gets processed by the writeRowFunction | ||
* @param {Map} headerQueryMap | ||
* @param {[{}]} dataset | ||
* @param {function (dataRow)} writeRowFunction | ||
*/ | ||
internals.generateDataRows = (headerQueryMap, dataset, writeRowFunction) => { | ||
const dataRows = []; | ||
if (!Array.isArray(dataset)) { | ||
@@ -304,6 +349,4 @@ dataset = [dataset]; | ||
let valueFound = true; | ||
for (let i = 0; i < dataset.length; ++i) { | ||
const dataRow = {}; | ||
const dataRow = []; | ||
for (const key of headerQueryMap.keys()) { | ||
@@ -322,2 +365,3 @@ | ||
else { | ||
temp = temp[queryPart]; | ||
@@ -329,16 +373,17 @@ } | ||
valueFound = true; | ||
temp = ''; | ||
} | ||
temp = internals.dateToISOString(temp); | ||
dataRow[key] = internals.escapeQuotesInString(temp); | ||
dataRow.push(internals.escapeQuotesInString(temp)); | ||
} | ||
dataRows.push(dataRow); | ||
writeRowFunction(dataRow); | ||
} | ||
const wb = XLSX.utils.book_new(); | ||
XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(dataRows, headerQueryMap.keys())); | ||
return wb; | ||
}; | ||
/** | ||
* @param {String} str | ||
* @returns {String} | ||
*/ | ||
internals.escapeQuotesInString = (str) => { | ||
@@ -353,2 +398,6 @@ | ||
/** | ||
* @param { Date | String} str | ||
* @returns {String} | ||
*/ | ||
internals.dateToISOString = (str) => { | ||
@@ -363,2 +412,7 @@ | ||
/** | ||
* @param {} route | ||
* @param {} method | ||
* @returns {String} | ||
*/ | ||
internals.createRouteMethodString = (route, method) => { | ||
@@ -365,0 +419,0 @@ |
{ | ||
"name": "hapi-csv", | ||
"version": "4.2.0", | ||
"version": "4.3.1", | ||
"description": "Hapi plugin for converting a Joi response schema and dataset to csv", | ||
@@ -27,2 +27,3 @@ "main": "lib/index.js", | ||
"async": "^2.6.1", | ||
"exceljs": "^1.6.3", | ||
"hoek": "^6.0.3", | ||
@@ -29,0 +30,0 @@ "xlsx": "^0.14.1" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
62501
1310
6
1
+ Addedexceljs@^1.6.3
+ Addedarchiver@3.1.1(transitive)
+ Addedarchiver-utils@2.1.0(transitive)
+ Addedarguments-extended@0.0.3(transitive)
+ Addedarray-extended@0.0.11(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbig-integer@1.6.52(transitive)
+ Addedbinary@0.3.0(transitive)
+ Addedbl@4.1.0(transitive)
+ Addedbluebird@3.4.7(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedbuffer-crc32@0.2.13(transitive)
+ Addedbuffer-indexof-polyfill@1.0.2(transitive)
+ Addedbuffers@0.1.1(transitive)
+ Addedchainsaw@0.1.0(transitive)
+ Addedcompress-commons@2.1.1(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedcrc@3.8.0(transitive)
+ Addedcrc32-stream@3.0.1(transitive)
+ Addeddate-extended@0.0.6(transitive)
+ Addeddeclare.js@0.0.8(transitive)
+ Addedduplexer2@0.1.4(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedes6-promise@3.3.1(transitive)
+ Addedexceljs@1.15.0(transitive)
+ Addedextended@0.0.6(transitive)
+ Addedextender@0.0.10(transitive)
+ Addedfast-csv@2.5.0(transitive)
+ Addedfs-constants@1.0.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfstream@1.0.12(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedimmediate@3.0.6(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-extended@0.0.10(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedjszip@3.10.1(transitive)
+ Addedlazystream@1.0.1(transitive)
+ Addedlie@3.3.0(transitive)
+ Addedlistenercount@1.0.1(transitive)
+ Addedlodash.defaults@4.2.0(transitive)
+ Addedlodash.difference@4.5.0(transitive)
+ Addedlodash.flatten@4.4.0(transitive)
+ Addedlodash.isplainobject@4.0.6(transitive)
+ Addedlodash.union@4.6.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedmoment@2.30.1(transitive)
+ Addednormalize-path@3.0.0(transitive)
+ Addedobject-extended@0.0.7(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpako@1.0.11(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedpromish@5.1.1(transitive)
+ Addedreadable-stream@2.3.83.6.2(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsax@1.4.1(transitive)
+ Addedsetimmediate@1.0.5(transitive)
+ Addedstring-extended@0.0.8(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedtar-stream@2.2.0(transitive)
+ Addedtmp@0.1.0(transitive)
+ Addedtraverse@0.3.9(transitive)
+ Addedunzipper@0.9.15(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedzip-stream@2.1.3(transitive)