Skip to content

gaslamp

Shedding light on easier data manipulation in Google Apps Script by introducing DataFrame operations and runtime type safety.

Logo

gaslamp is a Google Apps Script library for DataFrame operations and runtime type safety. It illuminates two dark corners of GAS data manipulation: raw spreadsheet data and the absence of runtime types. Inspired by pandas and polars, it wraps getValues() in a full DataFrame API and provides composable type guards through FlameWright — bringing structure and safety to a JavaScript-only runtime.

Why gaslamp?

Google Apps Script runs pure JavaScript at runtime — TypeScript types are erased. Without extra tooling, data from spreadsheets arrives as any[][], and there is no way to verify types at runtime.

gaslamp addresses two problems:

  • No DataFrame API in GASgetValues() returns raw 2D arrays. gaslamp wraps them in a DataFrame with select, filter, sortBy, groupBy, resampleBy, and more.
  • No runtime type safety in GAS — gaslamp's FlameWright system provides composable type guards that narrow types at runtime, not just at compile time.

Features

Category Description
DataFrame Core schema-free DataFrame named BareFrame and GroupedFrame for grouped operations, LazyFrame for lazy evaluation and
FlameFrame Schema validation gate combining BareFrame and FlameWright — validates data and returns { passed, failed }
Flame FlameWright, FlameGuards — runtime type guards and schema validation
Expression Chainable expression builder for filter conditions
Convert Bidirectional converters between row-oriented and column-oriented data
Logger CategoryLogger, AfterGlow — structured logging with category support
Gaslets Google Sheets, Drive, Calendar, Trigger integration utilities
Gears ClockSmith timing, Counter, JunkPocket caching
JestLite GAS-compatible testing framework (no Node.js required)

Installation

Script ID

Text Only
1l2aZO5RkhmDHUwtR3gnrqDIWw84K_T-NBdLP7-X0-BjcA06YU0nbgCNQ

Setup

  1. Open Libraries in your Google Apps Script project
  2. Paste the Script ID above
  3. Select version: HEAD (latest) or a fixed version for production
  4. Set identifier: gaslamp
  5. Click Save

Note: Use a fixed version in production. HEAD may include breaking changes.

Quick Start

BareFrame — spreadsheet data as a DataFrame

JavaScript
function example() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("master");

  // Load sheet data as a BareFrame
  const df = gaslamp.BareFrame.fromSheet(sheet);

  // Filter rows declaratively
  const active = df.filter(row => row.get("status") === "active");

  // Display as a table string
  console.log(active.toTableString());
}

FlameWright — runtime type guards

JavaScript
function validate() {
  const value = someExternalInput();

  // Narrow the type at runtime
  if (gaslamp.FlameGuards.isString(value)) {
    console.log(value.toUpperCase()); // value is typed as string here
  }

  // Schema-style validation
  const schema = {
    name: gaslamp.FlameGuards.isString,
    age:  gaslamp.FlameGuards.isNumber,
  };

  const isUser = gaslamp.FlameWright.fromSchema(schema);
  const data = { name: "Alice", age: 30 };

  if (isUser(data)) {
    console.log(data.name); // data is narrowed to { name: string; age: number }
  }
}

FlameFrame — schema-validated data

JavaScript
function validateAndProcess() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("master");
  const df = gaslamp.BareFrame.fromSheet(sheet);

  // Define a validation schema
  const schema = {
    name:  gaslamp.FlameGuards.isString,
    score: gaslamp.FlameGuards.isNumber,
  };

  // Validate and separate valid/invalid rows
  const { passed, failed } = gaslamp.FlameFrame.from(df, schema);

  if (failed.length > 0) {
    console.log("Invalid rows:", failed.display());
  } else {
    console.log(`All ${passed.length} rows are valid`);
  }
}

Expression — reusable filter conditions

JavaScript
function filterWithExpression() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("master");
  const df = gaslamp.BareFrame.fromSheet(sheet);

  // Build a condition as an Expression, then convert to a predicate
  const cond = gaslamp.Expression.col("score").ge(80);
  const highScorers = df.filter(cond.toFunction());

  console.log(highScorers.toTableString());
}

Performance

gaslamp is designed for GAS's constraints:

  • Column-oriented storage — reduces memory usage for large sheets
  • Lazy evaluationLazyFrame defers computation until needed
  • No Node.js dependencies — ES2020 target, GAS-compatible from day one
  • Batch sheet operations — minimizes API call overhead

Documentation

License

LGPL-3.0 — see LICENSE for details.

In short: Improvements to gaslamp must be shared, but projects using gaslamp can remain proprietary.


gaslamp — Shedding light on easier data manipulation in Google Apps Script by introducing DataFrame operations and runtime type safety.