Skip to main content
Version: 0.4

WASM / Browser

The @robotops/rosql npm package exposes the ROSQL parser and validator for browser environments. Use it to build editor integrations, live query validation, or custom UIs.

Install

npm install @robotops/rosql
# or
pnpm add @robotops/rosql

Usage

import init, { parse, validate, compile, get_completions } from '@robotops/rosql';

// Initialize the WASM module (call once before using other functions)
await init();

// Parse a query — returns a JS object (not a string)
const result = parse('FROM traces WHERE duration > 500 ms SINCE 1 hour ago');
// { ok: true, ast: { ... } } or { ok: false, error: { message, line, column, suggestion } }

// Validate syntax — returns { valid: boolean, errors: [...], warnings: [...] }
const validation = validate('INSERT INTO logs');
// { valid: false, errors: [{ message, line, column, suggestion }], warnings: [] }

// Compile to SQL — returns a JS object
const compiled = compile('FROM traces WHERE duration > 500 ms');
// { ok: true, sql: "SELECT ...", default_limit_applied: true, format_hint: "Table", visualization: null, warnings: [] }

// Get autocomplete suggestions at cursor position
const completions = get_completions('FROM ', 5);
// [{ "label": "traces", "kind": "DataSource" }, { "label": "logs", ... }, ...]

API reference

All functions return JavaScript objects directly (not JSON strings). They never throw — errors are returned as structured objects.

init(url?: string): Promise<void>

Initializes the WASM module. Must be called before using any other function.

Optionally accepts a URL to the .wasm file. If omitted, the module is resolved relative to the package.

parse(query: string): object

Parses a ROSQL query and returns an object:

// Success
{ ok: true; ast: object }

// Failure
{ ok: false; error: { message: string; line: number; column: number; suggestion: string | null } }

validate(query: string): object

Validates a ROSQL query. Also runs a compilation pass to surface NotImplemented warnings. Returns:

{
valid: boolean;
errors: Array<{ message: string; line: number; column: number; suggestion?: string }>;
warnings: Array<{ code: string; message: string; suggestion: string | null }>;
}

Use this for live editor feedback. warnings includes non-fatal issues such as ANOMALY without FACET, or reserved features like HEALTH().

compile(query: string): object

Compiles a ROSQL query to SQL (DuckDB dialect). Returns:

// Success
{
ok: true;
sql: string;
default_limit_applied: boolean;
format_hint: string; // e.g. "Table", "LineChart", "Gantt"
visualization: object | null; // axis and series hints for charting
warnings: Array<{ code: string; message: string; suggestion: string | null }>;
}

// Failure
{ ok: false; error: { message: string } }

get_completions(query: string, cursor: number): Array<object>

Returns autocomplete suggestions for an in-progress query at the given cursor position.

Array<{
label: string;
kind: 'DataSource' | 'Keyword' | 'Field' | 'Function';
}>

React editor integration

Example using validate for live error highlighting in a <textarea>:

import { useState, useEffect } from 'react';
import init, { validate } from '@robotops/rosql';

export function RosqlEditor() {
const [query, setQuery] = useState('FROM traces WHERE status = \'ERROR\'');
const [errors, setErrors] = useState<string[]>([]);
const [ready, setReady] = useState(false);

useEffect(() => {
init().then(() => setReady(true));
}, []);

const handleChange = (value: string) => {
setQuery(value);
if (ready) {
const result = validate(value);
setErrors(result.errors.map((e: { message: string }) => e.message));
}
};

return (
<div>
<textarea
value={query}
onChange={(e) => handleChange(e.target.value)}
rows={6}
style={{ width: '100%', fontFamily: 'monospace' }}
/>
{errors.length > 0 && (
<ul style={{ color: 'red' }}>
{errors.map((err, i) => <li key={i}>{err}</li>)}
</ul>
)}
</div>
);
}

Bundle size

The WASM binary adds approximately ~500KB to your bundle (gzipped). To avoid impacting initial load time, load it lazily:

// Lazy load on first use
let rosql: typeof import('@robotops/rosql') | null = null;

async function getRosql() {
if (!rosql) {
rosql = await import('@robotops/rosql');
await rosql.default();
}
return rosql;
}

Try it live

Try ROSQL in your browser