import type { Row } from '../types.ts'; // The rows of a GSF seed CSV (an app's or a PBC's data/*.csv): a header line, // then one record per line; a value is bare or double-quoted ("" is a quote // inside one). Values stay strings — a table's declared fields convert them // when the rows are stored, as GSF's loader does. An empty cell is left out of // its row (null), since SendTable sets only the non-empty cells // (SendTableOperation.createRecord, genesis-db, GSF v8.15.29). export function parseSeedCsv(text: string): Row[] { const records: string[][] = []; let record: string[] = []; let field = ''; let quoted = false; const endRecord = () => { record.push(field); if (record.some((value) => value !== '')) records.push(record); record = []; field = ''; }; for (let i = 0; i < text.length; i += 1) { const char = text[i]; if (quoted) { if (char === '"' && text[i + 1] === '"') { field += '"'; i += 1; } else if (char === '"') { quoted = false; } else { field += char; } } else if (char === '"') { quoted = true; } else if (char === ',') { record.push(field); field = ''; } else if (char === '\n' || char === '\r') { if (char === '\r' && text[i + 1] === '\n') i += 1; endRecord(); } else { field += char; } } endRecord(); const [header = [], ...rows] = records; return rows.map((values) => Object.fromEntries( header.flatMap((name, i) => (values[i] ? [[name.trim(), values[i]] as const] : [])), ), ); }