Skip to content

FlameFrame and Schema Validation

FlameFrame is a schema-validated wrapper around BareFrame. Start by reading your data into a BareFrame, then pass it to FlameFrame.from to validate each cell against a type schema.

JavaScript
const df = gaslamp.BareFrame.fromSheet(sheet);
const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

This keeps reading and validation as separate, composable steps — you can use BareFrame freely and add validation at any point.

For reading and manipulating data without validation, see DataFrame and Google Sheets.


Defining a Schema

A schema maps column names to FlameGuards type guard functions. FlameGuards provides built-in guards for common types.

JavaScript
const schema = {
  name: gaslamp.FlameGuards.isString,
  age:  gaslamp.FlameGuards.isNumber,
};

Available guards:

Guard Accepts
FlameGuards.isString string
FlameGuards.isNumber number (excludes NaN)
FlameGuards.isBoolean boolean
FlameGuards.isValidDate Date (excludes invalid dates)
FlameGuards.isNull null
FlameGuards.isUndefined undefined
FlameGuards.isStringOrNumber string \| number
FlameGuards.isArray unknown[]

See the API Reference for the full list.


Reading from a Sheet

The recommended workflow is to read with BareFrame.fromSheet, then validate with FlameFrame.from.

JavaScript
function example_fromSheet() {
  const sheet = SpreadsheetApp.getActiveSheet();

  // 1. Read raw data
  const df = gaslamp.BareFrame.fromSheet(sheet);

  // 2. Validate against schema
  const schema = {
    name: gaslamp.FlameGuards.isString,
    age:  gaslamp.FlameGuards.isNumber,
  };
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

  if (failed.length > 0) {
    console.warn(`Found ${failed.length} validation error(s).`);
    console.error(failed.display());
  } else {
    console.log(passed.display());
  }
}

Handling Validation Errors

FlameFrame.from returns { passed, failed }.

  • passed — a FlameFrame<T> containing only rows that passed all schema guards
  • failed — a BareFrame containing invalid rows with error messages in the invalid_message column (schema-free)
  • failed.length — number of invalid rows (check this to decide whether to proceed)

Each row in failed includes:

  • All original columns from the source DataFrame
  • invalid_message column — a string describing which fields failed and why
JavaScript
const df = gaslamp.BareFrame.fromColumns(
  { name: ["Alice", 999], age: [25, 30] },
);
const { passed, failed } = gaslamp.FlameFrame.from(df, {
  name: gaslamp.FlameGuards.isString,
  age: gaslamp.FlameGuards.isNumber,
});

failed.length;  // 1
failed.toColumns()["invalid_message"][0];
// "row: 1; name: got number"

Writing errors to a sheet

Use failed.toSheet(sheet) to write the error report to a sheet.

JavaScript
function example_errorReport() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const inputSheet = book.getSheetByName("Import");
  const errorSheet = book.getSheetByName("Errors")
    ?? book.insertSheet("Errors");

  const df = gaslamp.BareFrame.fromSheet(inputSheet);
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

  if (failed.length > 0) {
    failed.toSheet(errorSheet);
    console.warn(`${failed.length} error(s) written to Errors sheet.`);
  }
}

Strict Mode

Pass { strict: true } to throw a TypeError on the first validation error instead of collecting errors. Use this when you want to stop processing immediately on bad data.

JavaScript
const df = gaslamp.BareFrame.fromColumns({ name: [123], age: [25] });
const schema = {
  name: gaslamp.FlameGuards.isString,
  age:  gaslamp.FlameGuards.isNumber,
};
try {
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema, { strict: true });
  console.log(passed.display()); // only reached if validation passes
} catch (e) {
  console.log(e.message);
  // "FlameFrame validation failed | row 0 | field "name" | got number"
}

Writing to a Sheet

FlameFrame.toSheet works the same way as BareFrame.toSheet.

JavaScript
function example_toSheet() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName("Output");

  const df = gaslamp.BareFrame.fromColumns(
    { name: ["Alice", "Bob"], age: [25, 30] },
  );
  const schema = {
    name: gaslamp.FlameGuards.isString,
    age:  gaslamp.FlameGuards.isNumber,
  };
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

  if (failed.length === 0) {
    passed.toSheet(sheet);
  }
}

Append mode is also supported:

JavaScript
frame.toSheet(sheet, {
  clear: false,
  header: false,
  startRow: sheet.getLastRow() + 1,
});

Transforming a FlameFrame

FlameFrame extends BareFrame, so you can call transformation methods directly on frame. If you have access to the original df, use it instead — it's clearer and avoids creating a new intermediate BareFrame.

JavaScript
// Option 1: Use the original df if it's in scope
const adults = df.filter(row => row.get("age") >= 18);
const { passed, failed } = gaslamp.FlameFrame.from(adults, schema);

// Option 2: Use passed directly
const adults = passed.filter(row => row.get("age") >= 18);

Expression also works with frame.filter:

JavaScript
const adults = frame.filter(
  gaslamp.Expression.col("age").ge(18).toFunction()
);

See Expression Filtering for the full syntax.


Practical Workflow

A complete example: read from a sheet, validate, transform, and write results.

JavaScript
function workflow_validateAndExport() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const inputSheet  = book.getSheetByName("Employees");
  const outputSheet = book.getSheetByName("Seniors")
    ?? book.insertSheet("Seniors");
  const errorSheet  = book.getSheetByName("Errors")
    ?? book.insertSheet("Errors");

  const schema = {
    name:       gaslamp.FlameGuards.isString,
    age:        gaslamp.FlameGuards.isNumber,
    department: gaslamp.FlameGuards.isString,
  };

  // 1. Read and validate
  const df = gaslamp.BareFrame.fromSheet(inputSheet);
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

  // 2. Report errors
  if (failed.length > 0) {
    failed.toSheet(errorSheet);
    console.warn(`${failed.length} error(s) found. See Errors sheet.`);
  }

  // 3. Transform (use df directly if available, or passed)
  const result = df
    .filter((row) => row.get("age") >= 40)
    .select(["name", "department", "age"]);

  // 4. Write
  result.toSheet(outputSheet);
  console.log(`Exported ${result.length} rows to Seniors sheet.`);
}

Next Steps