({
fileName,
idField,
transformHeader = camelize,
parserOptions,
}: CSVLoaderOptions)
| 41 | * Loads entries from a CSV file. The file must contain an array of objects that contain unique `id` fields, or an object with string keys. |
| 42 | */ |
| 43 | export function csvLoader({ |
| 44 | fileName, |
| 45 | idField, |
| 46 | transformHeader = camelize, |
| 47 | parserOptions, |
| 48 | }: CSVLoaderOptions): Loader { |
| 49 | async function syncData( |
| 50 | filePath: string, |
| 51 | { logger, parseData, store, config }: LoaderContext, |
| 52 | ) { |
| 53 | const relativePath = relative(fileURLToPath(config.root), filePath); |
| 54 | |
| 55 | const csvStream = Papa.parse(Papa.NODE_STREAM_INPUT, { |
| 56 | dynamicTyping: true, |
| 57 | ...parserOptions, |
| 58 | header: true, |
| 59 | transformHeader: transformHeader === false ? undefined : transformHeader, |
| 60 | }); |
| 61 | |
| 62 | createReadStream(filePath).pipe(csvStream); |
| 63 | |
| 64 | await new Promise<void>((resolve, reject) => { |
| 65 | let count = 0; |
| 66 | let row = 0; |
| 67 | store.clear(); |
| 68 | csvStream.on("end", () => { |
| 69 | logger.info(`Loaded ${count} entries from ${fileName}`); |
| 70 | resolve(); |
| 71 | }); |
| 72 | csvStream.on("error", (error) => { |
| 73 | logger.error("Error reading data"); |
| 74 | reject(error); |
| 75 | }); |
| 76 | csvStream.on("data", async (data) => { |
| 77 | if (!idField) { |
| 78 | idField = Object.keys(data)[0]; |
| 79 | logger.info(`No ID field specified, using first column: ${idField}`); |
| 80 | if (!idField) { |
| 81 | csvStream.end(); |
| 82 | reject("No ID field found in CSV file"); |
| 83 | return; |
| 84 | } |
| 85 | } |
| 86 | row++; |
| 87 | if (!(idField in data) || !(data[idField] && data[idField] !== 0)) { |
| 88 | logger.warn(`No ID (${idField}) found in row ${row}. Skipping.`); |
| 89 | return; |
| 90 | } |
| 91 | count++; |
| 92 | const id = String(data[idField]); |
| 93 | const parsedData = await parseData({ |
| 94 | id, |
| 95 | data, |
| 96 | filePath: relativePath, |
| 97 | }); |
| 98 | store.set({ id, data: parsedData, filePath: relativePath }); |
| 99 | }); |
| 100 | }).catch((error) => { |
no test coverage detected