This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A TypeScript implementation of BMG, a relational algebra originally implemented in Ruby:
The aim is to provide relational algebra operators for arrays of JavaScript objects, NOT to implement an SQL compiler.
npm run test # Run all tests (vitest)
npm run test:watch # Run tests in watch mode
npm run build # Build the library (generates lib-definitions, bundles, and types)Run a single test file:
npx vitest run tests/operators/restrict.test.tsEntry point: src/index.ts - Exports Bmg factory function, all operators, and types
Core abstractions:
Relation<T>interface (src/types.ts) - Defines all relational operators with full TypeScript genericsMemoryRelation<T>(src/Relation/Memory.ts) - In-memory implementation wrapping an array of tuplesAsyncRelation<T>(src/async-types.ts) - Async version for streaming data sourcesBaseAsyncRelation<T>(src/AsyncRelation/Base.ts) - Async implementation using AsyncIterable
Operators pattern: Each operator exists as:
- Standalone function in
src/operators/<name>.ts- Works on arrays directly - Method on
MemoryRelation- Delegates to standalone function - Async version in
src/async-operators/<name>.tsfor AsyncRelation
Test fixtures: tests/fixtures.ts provides standard SUPPLIERS relation for tests.
- Relations NEVER have duplicates
- Order of tuples and order of attributes in a tuple are not important semantically
- Relations are sets of tuples; tuples are sets of (attr, value) pairs
- Two relations are equal if they have the exact same set of tuples
DEEis the relation with no attribute and one tupleDUMis the relation with no attribute and no tuple
- Use purely relational tests: compare obtained relation with expected using
isEqual - NEVER access the "first" tuple (there is no ordering)
- Use
r.restrict(...predicate...).one()to select a specific tuple for testing - Tests should cover
DUMandDEE
- Always check .claude/tasks for .md files
- Work on ONGOING tasks by default
- If you're asked to work on a TODO task, move it to ONGOING first
- Track your own subtasks in these .md task files
- You MUST commit those .md task files if you change them as a result of your work
- Add each operator with unit tests
- One commit per operator
- An operator MUST ALWAYS be provided on
RelationandAsyncRelation - Update README when adding operators
- Tests MUST succeed at all times
- Build MUST succeed at all times (check for typescript errors)
- When you commit, you MUST update the CHANGELOG
- The CHANGELOG is end-user oriented
- Track new features and briefly tells which APIs are improved
- You MUST clearly identify BROKEN apis too
Relational: restrict, where, exclude, project, allbut, extend, rename, prefix, suffix, constants, union, minus, intersect, matching, not_matching, join, left_join, cross_product, cross_join, image, summarize, group, ungroup, wrap, unwrap, autowrap, transform
Non-relational: one, yByX, toArray, isRelation, isEqual, toText