Skip to content

Commit

Permalink
fix: extract nested props in arrays as x.0.y
Browse files Browse the repository at this point in the history
also unwind empty arrays, prepending ! to the unwind opt
  • Loading branch information
0xfede committed Sep 13, 2022
1 parent 2215015 commit b5907d8
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 4 deletions.
11 changes: 10 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AnyMongoAbility, ForbiddenError, subject } from '@casl/ability';
import { deleteProperty, getProperty, setProperty } from 'dot-prop';
import { dot } from 'eredita';
import _ from 'lodash';
import { DateTime } from 'luxon';
import { ObjectId } from 'mongodb';
Expand Down Expand Up @@ -338,6 +339,7 @@ export function checkAbility(ability: AnyMongoAbility, resource: string, action:
export interface CSVOptions {
fields: string[] | { [key: string]: string };
unwind?: string;
forceUnwind?: boolean;
separator?: string;
decimal?: string;
quotes?: boolean;
Expand Down Expand Up @@ -367,13 +369,20 @@ export function toCSV(data: any[], options: CSVOptions): string {
data.forEach((originalItem) => {
const unwound: any[] = [];
if (options.unwind) {
if (options.unwind[0] === '!') {
options.forceUnwind = true;
options.unwind = options.unwind.substring(1);
}
if (originalItem[options.unwind]?.length) {
originalItem[options.unwind].forEach((i) => {
unwound.push({
...originalItem,
[options.unwind!]: i,
});
});
} else if (options.forceUnwind) {
originalItem[options.unwind] = undefined;
unwound.push(originalItem);
}
} else {
unwound.push(originalItem);
Expand All @@ -382,7 +391,7 @@ export function toCSV(data: any[], options: CSVOptions): string {
const l: string[] = [];
// TODO optimize with a transversal map
for (let k in fieldMap) {
const value: any = getProperty(item, k);
const value: any = dot(item, k);
if (options.decimal && typeof value === 'number') {
l.push(value.toString().replace('.', options.decimal));
} else if (value instanceof Date) {
Expand Down
68 changes: 65 additions & 3 deletions test/ts/pipeline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ XXX,YYY,qqq`);
});
});

it('should ship an object if the unwind field is not an array with at least an element (1)', function () {
it('should skip an object if the unwind field is not an array with at least an element (1)', function () {
csv_options = {
fields: ['a', 'b', 'c'],
header: true,
Expand All @@ -404,7 +404,7 @@ XXX,YYY,qqq`);
});
});

it('should ship an object if the unwind field is not an array with at least an element (2)', function () {
it('should skip an object if the unwind field is not an array with at least an element (2)', function () {
csv_options = {
fields: ['a', 'b', 'c'],
header: true,
Expand All @@ -425,7 +425,7 @@ XXX,YYY,qqq`);
});
});

it('should ship an object if the unwind field is not an array with at least an element (3)', function () {
it('should skip an object if the unwind field is not an array with at least an element (3)', function () {
csv_options = {
fields: ['a', 'b', 'c'],
header: true,
Expand All @@ -446,6 +446,68 @@ XXX,YYY,qqq`);
});
});

it('should unwind an empty array, if forced', function () {
csv_options = {
fields: ['a', 'b', 'c'],
header: true,
unwind: '!c',
};
csv_data = [
{ a: 'AAA', b: 'BBB' },
{ a: 'XXX', b: 'YYY', c: ['ppp', 'qqq'] },
];
return request
.get('/tests')
.expect(200)
.expect('Content-Type', /text\/csv/)
.then(({ text: data }) => {
data.should.equal(`a,b,c
AAA,BBB,
XXX,YYY,ppp
XXX,YYY,qqq`);
});
});

it('should return the requested nested fields as csv (1)', function () {
csv_options = {
fields: ['a', 'b', 'c.d'],
};
csv_data = [
{ a: 'AAA', b: 'BBB', c: { d: 1 } },
{ a: 'XXX', b: 'YYY', c: { d: 2 } },
];
return request
.get('/tests')
.expect(200)
.expect('Content-Type', /text\/csv/)
.then(({ text: data }) => {
data.should.equal(
`AAA,BBB,1
XXX,YYY,2`
);
});
});

it('should return the requested nested fields as csv (2)', function () {
csv_options = {
fields: ['a', 'b', 'c.0.d'],
};
csv_data = [
{ a: 'AAA', b: 'BBB', c: [{ d: 1 }, { d: 2 }] },
{ a: 'XXX', b: 'YYY', c: [{ d: 3 }, { d: 4 }] },
];
return request
.get('/tests')
.expect(200)
.expect('Content-Type', /text\/csv/)
.then(({ text: data }) => {
data.should.equal(
`AAA,BBB,1
XXX,YYY,3`
);
});
});

it('should format dates as ISO', function () {
csv_options = {
fields: ['a', 'b'],
Expand Down

0 comments on commit b5907d8

Please sign in to comment.