TypeScript API Reference
The teide-js package exposes a fluent, chainable API for loading data, building queries, and accessing results. All heavy computation runs on a dedicated background thread, with both synchronous and asynchronous execution paths.
Context
The Context is the entry point for all Teide operations. It manages the native engine lifecycle, including the background Teide thread and the C heap.
class Context {
constructor()
readCsvSync(path: string): Table
readCsv(path: string): Promise<Table>
executeSync(sql: string): Table | null // Table for queries, null for DDL/DML
execute(sql: string): Promise<Table | null>
destroy(): void // Also available via Symbol.dispose
}
Creating and Disposing
import { Context } from 'teide-js';
// Create a new context
const ctx = new Context();
// Use it...
// Option 1: explicit cleanup
ctx.destroy();
// Option 2: using Symbol.dispose (requires TypeScript 5.2+ or Node 20+)
{
using ctx = new Context();
// ctx is automatically destroyed at end of block
}
Loading CSV Data
// Synchronous
const table = ctx.readCsvSync('data/sales.csv');
console.log(`Loaded ${table.nRows} rows, ${table.nCols} columns`);
console.log('Columns:', table.columns);
// Asynchronous
const table = await ctx.readCsv('data/sales.csv');
Executing SQL
// DDL returns null
ctx.executeSync(`CREATE TABLE users (id INTEGER, name VARCHAR, age INTEGER)`);
// DML returns null
ctx.executeSync(`INSERT INTO users VALUES (1, 'Alice', 30), (2, 'Bob', 25)`);
// Queries return a Table
const result = ctx.executeSync(`SELECT * FROM users WHERE age > 20`);
console.log(result.nRows); // 2
// Async execution
const result = await ctx.execute(`SELECT name, age FROM users ORDER BY age DESC`);
Table
A Table represents a columnar result set. It provides metadata, column access, and serves as the starting point for the fluent query API.
class Table {
readonly nRows: number
readonly nCols: number
readonly columns: string[]
col(name: string): Series
filter(expr: Expr): Query
groupBy(...cols: string[]): GroupBy
sort(col: string, opts?: { descending?: boolean }): Query
head(n: number): Query
}
Inspecting Results
const table = ctx.readCsvSync('sales.csv');
console.log(`${table.nRows} rows x ${table.nCols} cols`);
console.log('Column names:', table.columns);
// Access individual columns
const revenue = table.col('revenue');
console.log('Revenue dtype:', revenue.dtype);
console.log('First 5 values:', Array.from(revenue.data.slice(0, 5)));
Starting Queries from a Table
import { col, lit } from 'teide-js';
// Filter
const expensive = table
.filter(col('price').gt(lit(100)))
.collectSync();
// Sort
const sorted = table
.sort('revenue', { descending: true })
.collectSync();
// Head (first N rows)
const preview = table.head(10).collectSync();
// Group by
const summary = table
.groupBy('region')
.agg(col('revenue').sum().alias('total_revenue'))
.collectSync();
Series
A Series represents a single column of data. It provides zero-copy access to the underlying C heap memory via TypedArrays — no data is copied between the native engine and JavaScript.
class Series {
readonly name: string
readonly dtype: string
readonly length: number
readonly data: TypedArray // Float64Array, Int32Array, BigInt64Array, etc.
readonly nullBitmap: Uint8Array | null
readonly indices: Int32Array | null // for SYM (dictionary) columns
readonly dictionary: string[] | null // for SYM (dictionary) columns
}
Numeric Columns
const prices = table.col('price');
console.log(prices.dtype); // "F64"
console.log(prices.length); // 1000
// Direct TypedArray access (zero-copy)
const data = prices.data; // Float64Array
const sum = data.reduce((a, b) => a + b, 0);
const avg = sum / data.length;
Dictionary (SYM) Columns
const regions = table.col('region');
console.log(regions.dtype); // "SYM"
console.log(regions.dictionary); // ["North", "South", "East", "West"]
console.log(regions.indices); // Int32Array [0, 1, 2, 0, 3, ...]
// Resolve the i-th value
const dict = regions.dictionary;
const idx = regions.indices;
for (let i = 0; i < regions.length; i++) {
console.log(dict[idx[i]]); // "North", "South", "East", ...
}
Null Handling
const ages = table.col('age');
const bitmap = ages.nullBitmap; // Uint8Array or null
if (bitmap) {
for (let i = 0; i < ages.length; i++) {
const byteIdx = i >> 3;
const bitIdx = i & 7;
const isNull = (bitmap[byteIdx] & (1 << bitIdx)) === 0;
if (!isNull) {
console.log(`Row ${i}: ${ages.data[i]}`);
}
}
}
Expr (Expression Builder)
Expressions represent computations that are evaluated lazily by the engine. Use the col() and lit() factory functions to create expression trees, then combine them with arithmetic, comparison, and logical operators.
function col(name: string): Expr
function lit(value: number | string | boolean): Expr
class Expr {
// Arithmetic
add(other: Expr): Expr
sub(other: Expr): Expr
mul(other: Expr): Expr
div(other: Expr): Expr
mod(other: Expr): Expr
// Comparison
eq(other: Expr): Expr
ne(other: Expr): Expr
lt(other: Expr): Expr
le(other: Expr): Expr
gt(other: Expr): Expr
ge(other: Expr): Expr
// Logical
and(other: Expr): Expr
or(other: Expr): Expr
not(): Expr
// Math
abs(): Expr
sqrt(): Expr
log(): Expr
exp(): Expr
ceil(): Expr
floor(): Expr
neg(): Expr
// Null
isNull(): Expr
// Aggregation
sum(): Expr
avg(): Expr
mean(): Expr // alias for avg()
min(): Expr
max(): Expr
count(): Expr
first(): Expr
last(): Expr
// Naming
alias(name: string): Expr
}
Building Expressions
import { col, lit } from 'teide-js';
// Column reference
const price = col('price');
// Literal value
const threshold = lit(100);
// Arithmetic
const margin = col('revenue').sub(col('cost'));
const taxed = col('price').mul(lit(1.2));
const perUnit = col('total').div(col('quantity'));
// Comparison
const isExpensive = col('price').gt(lit(100));
const isInStock = col('quantity').gt(lit(0));
// Logical combination
const filter = isExpensive.and(isInStock);
// Math functions
const logPrice = col('price').log();
const absChange = col('delta').abs();
// Null check
const hasMissing = col('email').isNull();
// Aggregation with alias
const totalRevenue = col('revenue').sum().alias('total_revenue');
const avgPrice = col('price').avg().alias('avg_price');
Complete Example
import { Context, col, lit } from 'teide-js';
const ctx = new Context();
const sales = ctx.readCsvSync('sales.csv');
// Multi-step analysis pipeline
const result = sales
.filter(col('quantity').gt(lit(0)))
.groupBy('region')
.agg(
col('revenue').sum().alias('total_revenue'),
col('revenue').avg().alias('avg_revenue'),
col('price').min().alias('min_price'),
col('price').max().alias('max_price'),
col('revenue').count().alias('num_sales')
)
.sort('total_revenue', { descending: true })
.head(10)
.collectSync();
for (const name of result.columns) {
console.log(`${name}:`, Array.from(result.col(name).data));
}
ctx.destroy();
Query
A Query represents a lazy chain of operations. No computation happens until you call collectSync() or collect(). Operations can be chained fluently.
class Query {
filter(expr: Expr): Query
groupBy(...cols: string[]): GroupBy
sort(col: string, opts?: { descending?: boolean }): Query
head(n: number): Query
collectSync(): Table
collect(): Promise<Table>
}
Chaining Operations
// All operations are lazy until collect
const query = table
.filter(col('status').eq(lit('active')))
.sort('created_at', { descending: true })
.head(100);
// Execute synchronously
const result = query.collectSync();
// Or execute asynchronously
const result = await query.collect();
Filter then Group
const result = table
.filter(col('year').ge(lit(2020)))
.groupBy('category')
.agg(
col('sales').sum().alias('total'),
col('sales').avg().alias('average')
)
.sort('total', { descending: true })
.collectSync();
GroupBy
A GroupBy is created from a Table or Query via .groupBy(). Call .agg() with aggregation expressions to produce a new Query.
class GroupBy {
agg(...exprs: Expr[]): Query
}
Aggregation Examples
// Single group key, multiple aggregations
const byRegion = table
.groupBy('region')
.agg(
col('revenue').sum().alias('total'),
col('revenue').avg().alias('avg'),
col('revenue').count().alias('n')
)
.collectSync();
// Multiple group keys
const byRegionYear = table
.groupBy('region', 'year')
.agg(
col('profit').sum().alias('total_profit'),
col('profit').first().alias('first_profit'),
col('profit').last().alias('last_profit')
)
.collectSync();