RayforceDB WASM SDK - High-performance columnar database in WebAssembly
npm install rayforce-wasmFull-featured JavaScript SDK for RayforceDB with zero-copy ArrayBuffer views over native vectors.
- š Zero-Copy Data Access - TypedArray views directly over WASM memory
- š Full Type System - All Rayforce types: scalars, vectors, lists, dicts, tables
- š Query Builder - Fluent API for building and executing queries
- š¾ Memory Efficient - No data copying for vector operations
- š CDN Ready - UMD bundle for script tag usage
- ā” SIMD Optimized - Native WASM SIMD support
``javascript
import { createRayforceSDK, Types } from 'rayforce-wasm';
// Initialize
const createRayforce = (await import('./rayforce.js')).default;
const wasm = await createRayforce();
const rf = createRayforceSDK(wasm);
// Evaluate expressions
const result = rf.eval('(+ 1 2 3)');
console.log(result.toJS()); // 6
// Create vectors with zero-copy access
const vec = rf.vector(Types.I64, [1, 2, 3, 4, 5]);
const view = vec.typedArray; // BigInt64Array - no copy!
view[0] = 100n;
console.log(vec.toJS()); // [100, 2, 3, 4, 5]
`
`html`
`bashFrom npm (coming soon)
npm install rayforce-wasm
API Reference
$3
`javascript
// ES6
import { createRayforceSDK, Types } from './rayforce.sdk.js';
const rf = createRayforceSDK(wasmModule);// UMD
const rf = await Rayforce.init({ wasmPath: './rayforce.js' });
`$3
`javascript
// Evaluate Rayfall expression
const result = rf.eval('(+ 1 2 3)');
console.log(result.toJS()); // 6// With source tracking (for better error messages)
const result = rf.eval('(sum data)', 'myfile.ray');
`$3
`javascript
// Scalars
rf.b8(true) // Boolean
rf.i64(42) // 64-bit integer
rf.f64(3.14) // 64-bit float
rf.symbol('name') // Interned symbol
rf.string('hello') // String
rf.date(new Date()) // Date
rf.time(new Date()) // Time
rf.timestamp(new Date()) // Timestamp// Vectors (with zero-copy TypedArray access)
rf.vector(Types.I64, [1, 2, 3])
rf.vector(Types.F64, 1000000) // Pre-allocate
// Containers
rf.list([1, 'two', 3.0]) // Mixed-type list
rf.dict({ a: 1, b: 2 }) // Dictionary
rf.table({ // Table
id: [1, 2, 3],
name: ['Alice', 'Bob', 'Carol'],
score: [95.5, 87.3, 92.1]
})
`$3
`javascript
// Create vector
const vec = rf.vector(Types.F64, 1000000);// Get TypedArray view (zero-copy!)
const view = vec.typedArray; // Float64Array
// Fast iteration
for (let i = 0; i < view.length; i++) {
view[i] = Math.random();
}
// Convert to JS array (copies data)
const jsArray = vec.toJS();
`$3
`javascript
// Create table
const table = rf.table({
id: [1, 2, 3],
name: ['Alice', 'Bob', 'Carol'],
score: [95.5, 87.3, 92.1]
});// Access columns
const names = table.col('name'); // Vector
const scores = table.col('score'); // Vector
// Access rows
const row = table.row(0); // Dict
console.log(row.toJS()); // { id: 1, name: 'Alice', score: 95.5 }
// Convert to arrays
console.log(table.toJS()); // { id: [...], name: [...], score: [...] }
console.log(table.toRows()); // [{ id: 1, ... }, { id: 2, ... }, ...]
// Metadata
console.log(table.columnNames()); // ['id', 'name', 'score']
console.log(table.rowCount); // 3
`$3
`javascript
// Select with filter
const result = table
.select('name', 'score')
.where(rf.col('score').gt(90))
.execute();// Aggregations
const stats = table
.select('department')
.withColumn('avg_score', rf.col('score').avg())
.withColumn('max_score', rf.col('score').max())
.groupBy('department')
.execute();
// Using expressions
const expr = rf.col('score').gt(80).and(rf.col('active').eq(true));
const filtered = table.where(expr).execute();
`$3
`javascript
import { Types } from 'rayforce-wasm';Types.LIST // 0 - Mixed-type list
Types.B8 // 1 - Boolean
Types.U8 // 2 - Unsigned byte
Types.I16 // 3 - 16-bit integer
Types.I32 // 4 - 32-bit integer
Types.I64 // 5 - 64-bit integer
Types.SYMBOL // 6 - Interned string
Types.DATE // 7 - Date
Types.TIME // 8 - Time
Types.TIMESTAMP // 9 - Timestamp
Types.F64 // 10 - 64-bit float
Types.GUID // 11 - UUID
Types.C8 // 12 - Character
Types.TABLE // 98 - Table
Types.DICT // 99 - Dictionary
`$3
`javascript
// Column reference
const col = rf.col('price');// Comparisons
col.eq(100) // =
col.ne(100) // <>
col.lt(100) // <
col.le(100) // <=
col.gt(100) // >
col.ge(100) // >=
// Logical
col.gt(50).and(col.lt(100))
col.eq(0).or(col.eq(100))
col.gt(0).not()
// Aggregations
col.sum()
col.avg()
col.min()
col.max()
col.count()
col.first()
col.last()
col.distinct()
`Build from Source
$3
- Emscripten SDK
- Make
$3
`bash
Clone repository
git clone https://github.com/RayforceDB/rayforce-wasm.git
cd rayforce-wasmInstall Emscripten (if not already installed)
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk && ./emsdk install latest && ./emsdk activate latest
source emsdk_env.sh
cd ..Build from GitHub sources
make appOr build from local ../rayforce sources
make devStart dev server
make serve
Open http://localhost:8080/examples/
`$3
`
dist/
āāā rayforce.js # WASM loader (ES6)
āāā rayforce.wasm # WASM binary
āāā rayforce.sdk.js # SDK module (ES6)
āāā rayforce.umd.js # SDK bundle (UMD)
āāā index.js # Entry point
`Performance
The SDK provides zero-copy access to WASM memory through TypedArray views:
`javascript
// Create 1M element vector - ~8ms
const vec = rf.vector(Types.F64, 1000000);// Get TypedArray view - ~0.01ms (just creates view)
const view = vec.typedArray;
// Fill via TypedArray - ~15ms
for (let i = 0; i < view.length; i++) {
view[i] = Math.random();
}
// Native sum - ~2ms
const sum = rf.eval(
(sum ${vec.toString()}));
``- Chrome 89+ (WASM SIMD)
- Firefox 89+ (WASM SIMD)
- Safari 15+ (WASM SIMD)
- Edge 89+ (WASM SIMD)
MIT License - see LICENSE