mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-04 05:19:12 -04:00
Merge d02443a288
into b47d132839
This commit is contained in:
commit
b31605c27c
6 changed files with 76 additions and 10 deletions
|
@ -65,6 +65,7 @@
|
|||
"emojilib": "^3.0.10",
|
||||
"figlet": "^1.7.0",
|
||||
"figue": "^1.2.0",
|
||||
"flatten-anything": "^4.0.1",
|
||||
"fuse.js": "^6.6.2",
|
||||
"highlight.js": "^11.7.0",
|
||||
"iarna-toml-esm": "^3.0.5",
|
||||
|
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
|
@ -92,6 +92,9 @@ dependencies:
|
|||
figue:
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
flatten-anything:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
fuse.js:
|
||||
specifier: ^6.6.2
|
||||
version: 6.6.2
|
||||
|
@ -5697,6 +5700,14 @@ packages:
|
|||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
/filter-anything@4.0.2:
|
||||
resolution: {integrity: sha512-tNBpTytI180+uGpKu4dFupbkA7rmEl+ZFo27mSeR8Ov80rpMDBbmLORGTsCkCN8s50aOS79P0sg3YUKz3Tr/4Q==}
|
||||
engines: {node: '>=18'}
|
||||
dependencies:
|
||||
is-what: 5.0.2
|
||||
ts-toolbelt: 9.6.0
|
||||
dev: false
|
||||
|
||||
/find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -5724,6 +5735,14 @@ packages:
|
|||
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
|
||||
dev: true
|
||||
|
||||
/flatten-anything@4.0.1:
|
||||
resolution: {integrity: sha512-Wz5tXB7Sgm54LHOqgbqvFlhKxzBZxA+TAv8AE28wfGpqk6zYkNauIS/ierU4VmNRokgzG2KnxhVYaUCXP+oPCQ==}
|
||||
engines: {node: '>=18'}
|
||||
dependencies:
|
||||
filter-anything: 4.0.2
|
||||
is-what: 5.0.2
|
||||
dev: false
|
||||
|
||||
/flex-js@1.0.5:
|
||||
resolution: {integrity: sha512-Z5uoLzOGtTB/nzaTVVBbwmxOHBzHovAGJHLXE1TUKsQuN1RRWMOWeA08J9RRKtAl9TH9tkaH6fpjA4sLf0DzQw==}
|
||||
dev: false
|
||||
|
@ -6494,6 +6513,11 @@ packages:
|
|||
resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
|
||||
dev: true
|
||||
|
||||
/is-what@5.0.2:
|
||||
resolution: {integrity: sha512-vI7Ui0qzNQ2ClDZd0bC7uqRk3T1imbX5cZODmVlqqdqiwmSIUX3CNSiRgFjFMJ987sVCMSa7xZeEDtpJduPg4A==}
|
||||
engines: {node: '>=18'}
|
||||
dev: false
|
||||
|
||||
/is-wsl@2.2.0:
|
||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -8610,6 +8634,10 @@ packages:
|
|||
typescript: 5.2.2
|
||||
dev: true
|
||||
|
||||
/ts-toolbelt@9.6.0:
|
||||
resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==}
|
||||
dev: false
|
||||
|
||||
/tslib@1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
|
7
src/tools/json-to-csv/flatten-anything.d.ts
vendored
Normal file
7
src/tools/json-to-csv/flatten-anything.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
declare module "flatten-anything" {
|
||||
export function flatten(objectOrArray: {
|
||||
[key in string]: any;
|
||||
}, untilDepth?: number): {
|
||||
[key in string]: any;
|
||||
};
|
||||
}
|
|
@ -3,6 +3,10 @@ import { convertArrayToCsv, getHeaders } from './json-to-csv.service';
|
|||
|
||||
describe('json-to-csv service', () => {
|
||||
describe('getHeaders', () => {
|
||||
it('extracts all the keys from the array of nested objects', () => {
|
||||
expect(getHeaders({ array: [{ a: { c: 1, d: 1 }, b: 2 }, { a: 3, c: 4 }] })).toEqual(['a.c', 'a.d', 'b', 'a', 'c']);
|
||||
});
|
||||
|
||||
it('extracts all the keys from the array of objects', () => {
|
||||
expect(getHeaders({ array: [{ a: 1, b: 2 }, { a: 3, c: 4 }] })).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
@ -20,7 +24,7 @@ describe('json-to-csv service', () => {
|
|||
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b
|
||||
1,2
|
||||
3,4"
|
||||
|
@ -33,7 +37,7 @@ describe('json-to-csv service', () => {
|
|||
{ a: 3, c: 4 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b,c
|
||||
1,2,
|
||||
3,,4"
|
||||
|
@ -45,7 +49,7 @@ describe('json-to-csv service', () => {
|
|||
{ a: null, b: 2 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b
|
||||
null,2"
|
||||
`);
|
||||
|
@ -57,7 +61,7 @@ describe('json-to-csv service', () => {
|
|||
{ b: 3 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b
|
||||
,2
|
||||
,3"
|
||||
|
@ -69,7 +73,7 @@ describe('json-to-csv service', () => {
|
|||
{ a: 'hello, world', b: 2 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b
|
||||
\\"hello, world\\",2"
|
||||
`);
|
||||
|
@ -80,10 +84,32 @@ describe('json-to-csv service', () => {
|
|||
{ a: 'hello "world"', b: 2 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a,b
|
||||
hello \\\\\\"world\\\\\\",2"
|
||||
`);
|
||||
});
|
||||
|
||||
it('converts an array of nested objects to a CSV string', () => {
|
||||
const array = [
|
||||
{ a: { c: 1, d: 1 }, b: 2 },
|
||||
{ a: 3, c: 4 },
|
||||
];
|
||||
|
||||
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||
"a.c,a.d,b,a,c
|
||||
1,1,2,,
|
||||
,,,3,4"
|
||||
`);
|
||||
});
|
||||
|
||||
it('converts an object to a CSV string', () => {
|
||||
const obj = { a: { c: 1, d: 1 }, b: 2 };
|
||||
|
||||
expect(convertArrayToCsv({ arrayOrObject: obj })).toMatchInlineSnapshot(`
|
||||
"a.c,a.d,b
|
||||
1,1,2"
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { flatten } from 'flatten-anything';
|
||||
|
||||
export { getHeaders, convertArrayToCsv };
|
||||
|
||||
function getHeaders({ array }: { array: Record<string, unknown>[] }): string[] {
|
||||
const headers = new Set<string>();
|
||||
|
||||
array.forEach(item => Object.keys(item).forEach(key => headers.add(key)));
|
||||
array.forEach(item => Object.keys(flatten(item)).forEach(key => headers.add(key)));
|
||||
|
||||
return Array.from(headers);
|
||||
}
|
||||
|
@ -26,10 +28,12 @@ function serializeValue(value: unknown): string {
|
|||
return valueAsString;
|
||||
}
|
||||
|
||||
function convertArrayToCsv({ array }: { array: Record<string, unknown>[] }): string {
|
||||
function convertArrayToCsv({ arrayOrObject }: { arrayOrObject: Record<string, unknown>[] | Record<string, unknown> }): string {
|
||||
const array = !Array.isArray(arrayOrObject) ? [arrayOrObject] : arrayOrObject;
|
||||
|
||||
const headers = getHeaders({ array });
|
||||
|
||||
const rows = array.map(item => headers.map(header => serializeValue(item[header])));
|
||||
const rows = array.map(item => headers.map(header => serializeValue(flatten(item)[header])));
|
||||
|
||||
return [headers.join(','), ...rows].join('\n');
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ function transformer(value: string) {
|
|||
if (value === '') {
|
||||
return '';
|
||||
}
|
||||
return convertArrayToCsv({ array: JSON5.parse(value) });
|
||||
return convertArrayToCsv({ arrayOrObject: JSON5.parse(value) });
|
||||
}, '');
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue