parent
							
								
									87984e2081
								
							
						
					
					
						commit
						d02443a288
					
				| @ -41,8 +41,8 @@ | ||||
|     "@tiptap/pm": "2.1.6", | ||||
|     "@tiptap/starter-kit": "2.1.6", | ||||
|     "@tiptap/vue-3": "2.0.3", | ||||
|     "@types/markdown-it": "^13.0.7", | ||||
|     "@types/figlet": "^1.5.8", | ||||
|     "@types/markdown-it": "^13.0.7", | ||||
|     "@vicons/material": "^0.12.0", | ||||
|     "@vicons/tabler": "^0.12.0", | ||||
|     "@vueuse/core": "^10.3.0", | ||||
| @ -62,6 +62,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
									
									
									
								
							| @ -86,6 +86,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 | ||||
| @ -5651,6 +5654,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'} | ||||
| @ -5678,6 +5689,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 | ||||
| @ -6448,6 +6467,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'} | ||||
| @ -8548,6 +8572,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…
	
		Reference in New Issue
	
	Block a user