( headers: string[], rows: Record<string, unknown>[] )
| 183 | * column-name mapping used when coercing row values. |
| 184 | */ |
| 185 | export function inferSchemaFromCsv( |
| 186 | headers: string[], |
| 187 | rows: Record<string, unknown>[] |
| 188 | ): { columns: ColumnDefinition[]; headerToColumn: Map<string, string> } { |
| 189 | const sample = rows.slice(0, CSV_SCHEMA_SAMPLE_SIZE) |
| 190 | const seen = new Set<string>() |
| 191 | const headerToColumn = new Map<string, string>() |
| 192 | |
| 193 | const columns = headers.map((header) => { |
| 194 | const base = sanitizeName(header) |
| 195 | let colName = base |
| 196 | let suffix = 2 |
| 197 | while (seen.has(colName.toLowerCase())) { |
| 198 | colName = `${base}_${suffix}` |
| 199 | suffix++ |
| 200 | } |
| 201 | seen.add(colName.toLowerCase()) |
| 202 | headerToColumn.set(header, colName) |
| 203 | |
| 204 | return { |
| 205 | name: colName, |
| 206 | type: inferColumnType(sample.map((r) => r[header])), |
| 207 | } satisfies ColumnDefinition |
| 208 | }) |
| 209 | |
| 210 | return { columns, headerToColumn } |
| 211 | } |
| 212 | |
| 213 | /** |
| 214 | * Coerces a single value to the requested column type. Returns `null` for |
no test coverage detected