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",
|
"emojilib": "^3.0.10",
|
||||||
"figlet": "^1.7.0",
|
"figlet": "^1.7.0",
|
||||||
"figue": "^1.2.0",
|
"figue": "^1.2.0",
|
||||||
|
"flatten-anything": "^4.0.1",
|
||||||
"fuse.js": "^6.6.2",
|
"fuse.js": "^6.6.2",
|
||||||
"highlight.js": "^11.7.0",
|
"highlight.js": "^11.7.0",
|
||||||
"iarna-toml-esm": "^3.0.5",
|
"iarna-toml-esm": "^3.0.5",
|
||||||
|
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
|
@ -92,6 +92,9 @@ dependencies:
|
||||||
figue:
|
figue:
|
||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
|
flatten-anything:
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1
|
||||||
fuse.js:
|
fuse.js:
|
||||||
specifier: ^6.6.2
|
specifier: ^6.6.2
|
||||||
version: 6.6.2
|
version: 6.6.2
|
||||||
|
@ -5697,6 +5700,14 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
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:
|
/find-up@4.1.0:
|
||||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -5724,6 +5735,14 @@ packages:
|
||||||
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
|
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
|
||||||
dev: true
|
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:
|
/flex-js@1.0.5:
|
||||||
resolution: {integrity: sha512-Z5uoLzOGtTB/nzaTVVBbwmxOHBzHovAGJHLXE1TUKsQuN1RRWMOWeA08J9RRKtAl9TH9tkaH6fpjA4sLf0DzQw==}
|
resolution: {integrity: sha512-Z5uoLzOGtTB/nzaTVVBbwmxOHBzHovAGJHLXE1TUKsQuN1RRWMOWeA08J9RRKtAl9TH9tkaH6fpjA4sLf0DzQw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -6494,6 +6513,11 @@ packages:
|
||||||
resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
|
resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/is-what@5.0.2:
|
||||||
|
resolution: {integrity: sha512-vI7Ui0qzNQ2ClDZd0bC7uqRk3T1imbX5cZODmVlqqdqiwmSIUX3CNSiRgFjFMJ987sVCMSa7xZeEDtpJduPg4A==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-wsl@2.2.0:
|
/is-wsl@2.2.0:
|
||||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -8610,6 +8634,10 @@ packages:
|
||||||
typescript: 5.2.2
|
typescript: 5.2.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/ts-toolbelt@9.6.0:
|
||||||
|
resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tslib@1.14.1:
|
/tslib@1.14.1:
|
||||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||||
dev: true
|
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('json-to-csv service', () => {
|
||||||
describe('getHeaders', () => {
|
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', () => {
|
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']);
|
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
|
"a,b
|
||||||
1,2
|
1,2
|
||||||
3,4"
|
3,4"
|
||||||
|
@ -33,7 +37,7 @@ describe('json-to-csv service', () => {
|
||||||
{ a: 3, c: 4 },
|
{ a: 3, c: 4 },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||||
"a,b,c
|
"a,b,c
|
||||||
1,2,
|
1,2,
|
||||||
3,,4"
|
3,,4"
|
||||||
|
@ -45,7 +49,7 @@ describe('json-to-csv service', () => {
|
||||||
{ a: null, b: 2 },
|
{ a: null, b: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||||
"a,b
|
"a,b
|
||||||
null,2"
|
null,2"
|
||||||
`);
|
`);
|
||||||
|
@ -57,7 +61,7 @@ describe('json-to-csv service', () => {
|
||||||
{ b: 3 },
|
{ b: 3 },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||||
"a,b
|
"a,b
|
||||||
,2
|
,2
|
||||||
,3"
|
,3"
|
||||||
|
@ -69,7 +73,7 @@ describe('json-to-csv service', () => {
|
||||||
{ a: 'hello, world', b: 2 },
|
{ a: 'hello, world', b: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||||
"a,b
|
"a,b
|
||||||
\\"hello, world\\",2"
|
\\"hello, world\\",2"
|
||||||
`);
|
`);
|
||||||
|
@ -80,10 +84,32 @@ describe('json-to-csv service', () => {
|
||||||
{ a: 'hello "world"', b: 2 },
|
{ a: 'hello "world"', b: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(convertArrayToCsv({ array })).toMatchInlineSnapshot(`
|
expect(convertArrayToCsv({ arrayOrObject: array })).toMatchInlineSnapshot(`
|
||||||
"a,b
|
"a,b
|
||||||
hello \\\\\\"world\\\\\\",2"
|
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 };
|
export { getHeaders, convertArrayToCsv };
|
||||||
|
|
||||||
function getHeaders({ array }: { array: Record<string, unknown>[] }): string[] {
|
function getHeaders({ array }: { array: Record<string, unknown>[] }): string[] {
|
||||||
const headers = new Set<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);
|
return Array.from(headers);
|
||||||
}
|
}
|
||||||
|
@ -26,10 +28,12 @@ function serializeValue(value: unknown): string {
|
||||||
return valueAsString;
|
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 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');
|
return [headers.join(','), ...rows].join('\n');
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ function transformer(value: string) {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return convertArrayToCsv({ array: JSON5.parse(value) });
|
return convertArrayToCsv({ arrayOrObject: JSON5.parse(value) });
|
||||||
}, '');
|
}, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue