( csvText: string, fields: DbField[], idFieldId: string, genId: GenId = defaultGenId )
| 104 | * id cell get a fresh UUID. Returns rows keyed by field.id. |
| 105 | */ |
| 106 | export function parseRows( |
| 107 | csvText: string, |
| 108 | fields: DbField[], |
| 109 | idFieldId: string, |
| 110 | genId: GenId = defaultGenId |
| 111 | ): DbRow[] { |
| 112 | const grid = parseCsv(csvText) |
| 113 | if (grid.length === 0) return [] |
| 114 | const headers = grid[0] |
| 115 | // header name -> column index |
| 116 | const colByName = new Map<string, number>() |
| 117 | headers.forEach((h, idx) => { |
| 118 | if (!colByName.has(h)) colByName.set(h, idx) |
| 119 | }) |
| 120 | const idField = fields.find((f) => f.id === idFieldId) |
| 121 | |
| 122 | const out: DbRow[] = [] |
| 123 | for (let r = 1; r < grid.length; r++) { |
| 124 | const raw = grid[r] |
| 125 | const cells: Record<string, string> = {} |
| 126 | for (const field of fields) { |
| 127 | const col = colByName.get(field.name) |
| 128 | cells[field.id] = col === undefined ? '' : (raw[col] ?? '') |
| 129 | } |
| 130 | let id = idField ? cells[idField.id] : '' |
| 131 | if (!id) { |
| 132 | id = genId() |
| 133 | if (idField) cells[idField.id] = id |
| 134 | } |
| 135 | out.push({ id, cells }) |
| 136 | } |
| 137 | return out |
| 138 | } |
| 139 | |
| 140 | /** Serialize rows back to CSV text (header from field.name in field order). */ |
| 141 | export function serializeRows(rows: DbRow[], fields: DbField[]): string { |
no test coverage detected