Carmen LabsCarmen Labs

Parser Contract

The signature, inputs, outputs, and constraints a conforming parser must satisfy.

Parser Contract

The parser transforms normalized input into a view-specific data model. Physical-format interpretation happens earlier in a Source Adapter; the component downstream should never need to understand the source.

Signature

export default async function parse(input: any, context: any): Promise<unknown>;
  • input — the normalized representation of the source file or source directory selection, shaped according to the capability declared in accepts. See Capabilities for the exact shape per capability.
  • context — everything else the parser is allowed to know:
{
  input,      // data normalized by a Source Adapter
  source,     // declared source metadata, not file handles
  settings,   // the manifest's settings, merged with any runtime overrides
  resources,  // resolved paths under resources/
  workspace   // workspace-level metadata (no arbitrary fs access)
}
  • Return value — any JSON-serializable data model. This becomes the data prop passed to the component.

Example

export default async function parse(input: any, context: any) {
  const rows = input.rows ?? [];
 
  const totalSales = rows.reduce((sum: number, row: any) => {
    return sum + Number(row.Total ?? row.total ?? 0);
  }, 0);
 
  const salesByMonth = rows.map((row: any) => ({
    month: row.Month ?? row.month,
    total: Number(row.Total ?? row.total ?? 0)
  }));
 
  const topClients = [...rows]
    .sort((a: any, b: any) => Number(b.Total ?? b.total ?? 0) - Number(a.Total ?? a.total ?? 0))
    .slice(0, context.settings?.topClientsLimit ?? 10);
 
  return { totalSales, salesByMonth, topClients };
}

Constraints (MUST / MUST NOT)

  • The parser MUST NOT read files directly. It only sees the normalized input it is handed, even when the source is a directory.
  • The parser MUST NOT use absolute paths. Any path it produces or consumes is relative.
  • The parser MUST be a pure function of (input, context) — same inputs, same output. No reliance on hidden global or session state.
  • The parser MUST be re-executable: running it again after the declared source changes should produce an updated, correct data model without manual intervention.
  • The parser SHOULD fail with a clear, catchable error rather than throwing something opaque when input doesn't match what it expects (e.g., an expected column is missing) — the runtime surfaces this to the user with an option to regenerate.
  • The parser SHOULD verify that input carries the information the view was built for — not merely that it has the declared shape — and fail with the same kind of clear error when it recognizably does not. The runtime guarantees the shape of the normalized input, never its meaning.

What the runtime guarantees the parser

  • input has already been produced by the selected Source Adapter according to the capability the MView declared in accepts — the parser is not responsible for interpreting raw source bytes.
  • context.source describes the file or declared directory selection but does not grant filesystem access.
  • context.settings is the manifest's settings, already merged with any user overrides.

Relationship to the component

The parser's return value is opaque to the runtime — it's whatever shape the paired component expects. The Component Contract defines what happens next.

Contrato del parser

La firma, entradas, salidas y restricciones que debe cumplir un parser conforme.

Contrato del parser

El parser transforma la entrada normalizada en un modelo de datos específico de la vista. La interpretación del formato físico ocurre antes, en un Source Adapter; el componente posterior no debería necesitar comprender la fuente.

Firma

export default async function parse(input: any, context: any): Promise<unknown>;
  • input — la representación normalizada del archivo o de la selección del directorio fuente, con la forma correspondiente a la capacidad declarada en accepts. Ver Capacidades para la forma exacta por capacidad.
  • context — todo lo demás que el parser puede conocer:
{
   input,      // datos normalizados por un Source Adapter
  source,     // metadatos declarados de la fuente, no file handles
  settings,   // settings del manifiesto, combinados con overrides del runtime
  resources,  // rutas resueltas bajo resources/
  workspace   // metadatos del workspace (sin acceso fs arbitrario)
}
  • Valor de retorno — cualquier modelo de datos serializable como JSON. Esto se convierte en la prop data que recibe el componente.

Ejemplo

export default async function parse(input: any, context: any) {
  const rows = input.rows ?? [];
 
  const totalSales = rows.reduce((sum: number, row: any) => {
    return sum + Number(row.Total ?? row.total ?? 0);
  }, 0);
 
  const salesByMonth = rows.map((row: any) => ({
    month: row.Month ?? row.month,
    total: Number(row.Total ?? row.total ?? 0)
  }));
 
  const topClients = [...rows]
    .sort((a: any, b: any) => Number(b.Total ?? b.total ?? 0) - Number(a.Total ?? a.total ?? 0))
    .slice(0, context.settings?.topClientsLimit ?? 10);
 
  return { totalSales, salesByMonth, topClients };
}

Restricciones (DEBE / NO DEBE)

  • El parser NO DEBE leer archivos directamente. Solo ve el input normalizado que recibe, incluso cuando la fuente es un directorio.
  • El parser NO DEBE usar rutas absolutas. Toda ruta que produzca o consuma es relativa.
  • El parser DEBE ser una función pura de (input, context): mismas entradas, misma salida. Sin depender de estado global o de sesión oculto.
  • El parser DEBE ser reejecutable: ejecutarlo de nuevo después de que cambie la fuente declarada debe producir un modelo de datos actualizado y correcto sin intervención manual.
  • El parser DEBERÍA fallar con un error claro y capturable, en lugar de lanzar algo opaco cuando input no coincide con lo esperado (por ejemplo, falta una columna esperada); el runtime muestra esto al usuario con una opción para regenerar.
  • El parser DEBERÍA verificar que input porta la información para la que se construyó la vista — no solo que tiene la forma declarada — y fallar con el mismo tipo de error claro cuando reconociblemente no la porta. El runtime garantiza la forma de la entrada normalizada, nunca su significado.

Lo que el runtime garantiza al parser

  • input ya fue producido por el Source Adapter seleccionado según la capacidad que la MView declaró en accepts; el parser no es responsable de interpretar bytes raw de la fuente.
  • context.source describe el archivo o la selección declarada del directorio, pero no concede acceso al filesystem.
  • context.settings son los settings del manifiesto, ya combinados con cualquier override del usuario.

Relación con el componente

El valor de retorno del parser es opaco para el runtime: tiene la forma que espera el componente emparejado. El Contrato del componente define lo que ocurre después.