Comparing version 4.1.2 to 4.2.0
@@ -104,3 +104,3 @@ 'use strict'; | ||
const xlsx = internals.processSchema(schema, resolvedSchemasObject, request.response.source, options.resultKey, internals.headerQueryMapToExcel); | ||
const excel = XLSX.write(xlsx, { bookType:'xlsx', bookSST:true, type: 'base64' }); | ||
const excel = XLSX.write(xlsx, { bookType: 'xlsx', bookSST: false, type: 'buffer', compression: true, ...options.excelWriteOptions }); | ||
const response = reply(excel); | ||
@@ -107,0 +107,0 @@ return response.encoding('base64').type(`${preferredType}; charset=${response.settings.charset}; header=present;`).header(`'content-disposition', 'attachment'; filename=${fileName}.xlsx;`).header('Content-Length', excel.length); |
{ | ||
"name": "hapi-csv", | ||
"version": "4.1.2", | ||
"version": "4.2.0", | ||
"description": "Hapi plugin for converting a Joi response schema and dataset to csv", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"test": "lab -a code -vL --lint-fix -t 95 -I cptable" | ||
"test": "lab -a code -vL --lint-fix -t 97 -I cptable" | ||
}, | ||
@@ -18,3 +18,6 @@ "repository": { | ||
"joi", | ||
"schema" | ||
"schema", | ||
"excel", | ||
"convert", | ||
"export" | ||
], | ||
@@ -21,0 +24,0 @@ "author": "Salesflare Team", |
@@ -151,2 +151,18 @@ # hapi-csv [![Build Status](https://travis-ci.org/Salesflare/hapi-csv.svg?branch=master)](https://travis-ci.org/Salesflare/hapi-csv) | ||
]) | ||
``` | ||
``` | ||
### Excel | ||
You can also enable Excel conversion: | ||
```javascript | ||
server.register({ | ||
register: require('hapi-csv'), | ||
options: { | ||
enableExcel: true, | ||
excelWriteOptions: { /* compression: false */ } | ||
} | ||
}, ... | ||
``` | ||
`excelWriteOptions` takes anything for [https://github.com/SheetJS/js-xlsx#writing-options](https://github.com/SheetJS/js-xlsx#writing-options) |
@@ -7,4 +7,5 @@ 'use strict'; | ||
const Hapi = require('hapi'); | ||
const HapiCsv = require('../lib/index'); | ||
const HapiCsv = require('..'); | ||
const lab = exports.lab = Lab.script(); | ||
@@ -728,3 +729,3 @@ const describe = lab.experiment; | ||
it('Uses dynamic schemas: resolver function throws an error', (done) => { | ||
it('Uses dynamic schemas: resolver function throws an error', () => { | ||
@@ -741,50 +742,60 @@ const user = { | ||
return server.register({ | ||
register: HapiCsv | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.register({ | ||
register: HapiCsv | ||
}, (err) => { | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
expect(err, 'error').to.not.exist(); | ||
return reply(user); | ||
}, | ||
response: { | ||
schema: Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number(), | ||
tag: Joi.object() | ||
}) | ||
}, | ||
plugins: { | ||
'hapi-csv': { | ||
'tag': (request, callback) => { | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return callback(new Error('ERROR')); | ||
return reply(user); | ||
}, | ||
response: { | ||
schema: Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number(), | ||
tag: Joi.object() | ||
}) | ||
}, | ||
plugins: { | ||
'hapi-csv': { | ||
'tag': (request, callback) => { | ||
return callback(new Error('ERROR')); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}]); | ||
}]); | ||
return server.initialize((err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
} | ||
}, (res) => { | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
} | ||
}, (res) => { | ||
expect(res.statusCode, 'statusCode').to.equal(500); | ||
expect(res.statusCode, 'statusCode').to.equal(500); | ||
return server.stop(done); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -798,3 +809,3 @@ }); | ||
it('Uses the result key', (done) => { | ||
it('Uses the result key', () => { | ||
@@ -819,51 +830,61 @@ const result = { | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items' | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.object({ | ||
page: Joi.number(), | ||
items: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
}) | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items' | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.object({ | ||
page: Joi.number(), | ||
items: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
}) | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.result, 'result').to.equal(userCSV); | ||
expect(res.headers['content-type']).to.equal('text/csv; charset=utf-8; header=present;'); | ||
expect(res.headers['content-disposition']).to.equal('attachment;'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
} | ||
}, (res) => { | ||
expect(res.result, 'result').to.equal(userCSV); | ||
expect(res.headers['content-type']).to.equal('text/csv; charset=utf-8; header=present;'); | ||
expect(res.headers['content-disposition']).to.equal('attachment;'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -874,3 +895,3 @@ }); | ||
it('Ignores the result key if not used in the response', (done) => { | ||
it('Ignores the result key if not used in the response', () => { | ||
@@ -892,48 +913,58 @@ const result = [{ | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items' | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items' | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.result, 'result').to.equal(userCSV); | ||
expect(res.headers['content-type']).to.equal('text/csv; charset=utf-8; header=present;'); | ||
expect(res.headers['content-disposition']).to.equal('attachment;'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'text/csv' | ||
} | ||
}, (res) => { | ||
expect(res.result, 'result').to.equal(userCSV); | ||
expect(res.headers['content-type']).to.equal('text/csv; charset=utf-8; header=present;'); | ||
expect(res.headers['content-disposition']).to.equal('attachment;'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -947,3 +978,3 @@ }); | ||
it('Transforms the response to an xlsx format', (done) => { | ||
it('Transforms the response to an xlsx format', () => { | ||
@@ -960,3 +991,3 @@ const result = [{ | ||
const expectedString = '<si><t>first_name</t></si><si><t>last_name</t></si><si><t>age</t></si><si><t>firstName1</t></si><si><t>lastName1</t></si><si><t>firstName2</t></si><si><t>lastName2</t></si>'; | ||
const expectedString = '<sheetData><row r="1"><c r="A1" t="str"><v>first_name</v></c><c r="B1" t="str"><v>last_name</v></c><c r="C1" t="str"><v>age</v></c></row><row r="2"><c r="A2" t="str"><v>firstName1</v></c><c r="B2" t="str"><v>lastName1</v></c><c r="C2"><v>25</v></c></row><row r="3"><c r="A3" t="str"><v>firstName2</v></c><c r="B3" t="str"><v>lastName2</v></c><c r="C3"><v>27</v></c></row></sheetData>'; | ||
@@ -966,48 +997,59 @@ const server = new Hapi.Server(); | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true, | ||
excelWriteOptions: { compression: false } | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test.xlsx', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.payload, 'payload').to.include(expectedString); | ||
expect(res.headers['content-type']).to.equal('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8; header=present;'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test.xlsx', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
} | ||
}, (res) => { | ||
expect(res.payload, 'payload').to.include(expectedString); | ||
expect(res.headers['content-type']).to.equal('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8; header=present;'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -1018,3 +1060,3 @@ }); | ||
it('Transforms the response to an xlsx format', (done) => { | ||
it('Transforms the response to an xlsx format without compression', () => { | ||
@@ -1027,3 +1069,3 @@ const result = { | ||
const expectedString = '<si><t>first_name</t></si><si><t>last_name</t></si><si><t>age</t></si><si><t>lastName</t></si>'; | ||
const expectedString = '<sheetData><row r="1"><c r="A1" t="str"><v>first_name</v></c><c r="B1" t="str"><v>last_name</v></c><c r="C1" t="str"><v>age</v></c></row><row r="2"><c r="B2" t="str"><v>lastName</v></c><c r="C2"><v>27</v></c></row></sheetData>'; | ||
@@ -1033,48 +1075,59 @@ const server = new Hapi.Server(); | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string().allow(null), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
).single() | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true, | ||
excelWriteOptions: { compression: false } | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test.xlsx', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string().allow(null), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
).single() | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.payload, 'payload').to.include(expectedString); | ||
expect(res.headers['content-type']).to.equal('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8; header=present;'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test.xlsx?a=b', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
} | ||
}, (res) => { | ||
expect(res.payload, 'payload').to.include(expectedString); | ||
expect(res.headers['content-type']).to.equal('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8; header=present;'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -1085,3 +1138,3 @@ }); | ||
it('Ignores the xlsx when enableExcel is false', (done) => { | ||
it('Ignores the xlsx when enableExcel is false', () => { | ||
@@ -1101,48 +1154,58 @@ const result = [{ | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: false | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: false | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.statusCode, 'statusCode').to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/json; charset=utf-8'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
} | ||
}, (res) => { | ||
expect(res.statusCode, 'statusCode').to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/json; charset=utf-8'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -1153,3 +1216,3 @@ }); | ||
it('Ignores the xlsx when there is no xlsx extension or xlsx accept header', (done) => { | ||
it('Ignores the xlsx when there is no xlsx extension or xlsx accept header', () => { | ||
@@ -1169,48 +1232,58 @@ const result = [{ | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true | ||
} | ||
}, (err) => { | ||
return new Promise((resolve, reject) => { | ||
expect(err, 'error').to.not.exist(); | ||
server.route([{ | ||
method: 'GET', | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
return server.register({ | ||
register: HapiCsv, | ||
options: { | ||
resultKey: 'items', | ||
enableExcel: true | ||
} | ||
}]); | ||
}, (err) => { | ||
return server.initialize((err) => { | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
server.route([{ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'application/json' | ||
path: '/test', | ||
config: { | ||
handler: function (request, reply) { | ||
return reply(result); | ||
}, | ||
response: { | ||
schema: Joi.array().items( | ||
Joi.object().keys({ | ||
first_name: Joi.string(), | ||
last_name: Joi.string(), | ||
age: Joi.number() | ||
}) | ||
) | ||
} | ||
} | ||
}, (res) => { | ||
}]); | ||
expect(res.statusCode, 'statusCode').to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/json; charset=utf-8'); | ||
return server.initialize((err) => { | ||
return server.stop(done); | ||
expect(err, 'error').to.not.exist(); | ||
return server.inject({ | ||
method: 'GET', | ||
url: '/test', | ||
headers: { | ||
'Accept': 'application/json' | ||
} | ||
}, (res) => { | ||
expect(res.statusCode, 'statusCode').to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/json; charset=utf-8'); | ||
return server.stop((err) => { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(); | ||
}); | ||
}); | ||
}); | ||
@@ -1217,0 +1290,0 @@ }); |
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
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
61657
1256
167