mwg API
    Preparing search index...

    Type Alias CsvColumnType

    CsvColumnType: "string" | "number" | "boolean" | "list" | "map"

    A header-row CSV into an array of typed row objects - so a content designer edits a spreadsheet instead of a .ts object literal for a table shaped like actors.AffixTable, actors.LootTable, or any other array-of-records a game defines. The same precedent i18n's parseFTL already set: this takes a raw string and has no opinion on how that string reached the game (a small table can sit in a .ts template literal; a larger one loads through a bundler's raw-text import - Vite resolves a ?raw-suffixed path to its file's contents as a plain string - or through a game's own asset pipeline) - mwg supplies the parsing, not the loading.

    Every cell is a string until a column says otherwise: columns names which fields are 'number'/'boolean'/'list' (semicolon-separated by default, for a field shaped like AffixDef.kinds) /'map' (semicolon-separated key=value pairs, for a per-row property bag such as { str: '2', dex: '-1' } a game reads its own way) - and an undeclared column stays a plain string. An empty cell omits that field from the row entirely, the same as never setting an optional property - so a blank curse column reads exactly like the curse?: boolean it fills never being set.

    Follows RFC 4180 far enough for real game-data text: a quoted field may contain the delimiter, a newline, or an escaped "" for a literal quote, which a naive split(',') cannot survive the moment a description contains a comma.

    What this cannot hold: a core.ReactionTable rule's when/action are executable code, not data, so no cell format expresses them - the same boundary AffixDef.id already draws (a string the game interprets, mwg never does). A CSV row can drive which reactions a game builds at startup (an id, a comparison string like 'hp<=0.25', a threshold number a 'number' column already coerces) with the game's own code turning each row into a real ReactionRule; it cannot hold the rule's logic itself.

    import { parseCSV } from '@datamoc/mw_games/core';
    import type { AffixDef, AffixTable } from '@datamoc/mw_games/actors';

    const csv = `id,trigger,weight,curse,description
    blazing,strike,3,,Ignites the victim
    wayward,strike,1,true,"Cursed: -3 accuracy"`;

    const table: AffixTable = {
    entries: parseCSV<AffixDef>(csv, { columns: { weight: 'number', curse: 'boolean' } }),
    };
    console.log(table.entries[1]); // { id: 'wayward', trigger: 'strike', weight: 1, curse: true, description: 'Cursed: -3 accuracy' }