Source: clarity:SDK/javascript/clarity-sdk.js
The Clarity JavaScript SDK targets browser and Node.js environments, with Web Worker offloading for decode-heavy workloads.
Two classes exported: OptimizedClarityDecoder (also exported as ClarityDecoder) and OptimizedClarityClient (also exported as ClarityClient). Supports both CommonJS (module.exports) and ES module (export) environments.
The JS SDK is now read/query-only. The write methods (
write/writeFast/writeBuffered), the HA shadow dual-write helpers, and themapped_tagswrite/find-or-create path were removed (the ~300-line reduction from 1235 → 936 lines). Client endpoints also moved off the old/api/…prefix onto/exactapi/…. For writes, use the Python SDK or the REST API directly.
f64 value width — the decoders accept both the old
f32and the newf64wire encodings, branching on the payload'sformat_version(c9fceb2). See Storage Engine § Binary response formats.
clarity:SDK/javascript/clarity-sdk.js:17-23
| Constant | Value | Purpose |
|---|---|---|
BUFFER_POOL_SIZE |
10 | Max pooled ArrayBuffers |
CACHE_SIZE |
100 | LRU cache max entries |
CACHE_TTL |
60000 ms | LRU cache TTL |
CONNECTION_TIMEOUT |
5000 ms | HTTP connection timeout |
KEEP_ALIVE_TIMEOUT |
30000 ms | Keep-alive idle timeout |
clarity:SDK/javascript/clarity-sdk.js:27-52
Pool of up to 10 ArrayBuffer instances for reuse across decode calls. Only buffers ≤1 MB are pooled; larger buffers are not returned to the pool.
clarity:SDK/javascript/clarity-sdk.js:57-94
Map-backed LRU with TTL eviction. 100 entries max, 60 s TTL default. TTL check on get; stale entries are deleted and null returned.
clarity:SDK/javascript/clarity-sdk.js:99-163
Unified binary reader for Node.js (Buffer) and browser (DataView) environments. Detected at construction. All reads are little-endian.
Methods: readUInt32, readUInt16, readBigUInt64, readFloat32, readFloat64 (clarity:SDK/javascript/clarity-sdk.js:144-150 — Node readDoubleLE / browser getFloat64, +8 offset), readString(length), readBytes(length).
BigUInt64 values are cast to Number immediately (precision loss beyond 2^53).
clarity:SDK/javascript/clarity-sdk.js:176-471
Static decoder class with a shared BufferPool and LRUCache. Cache key is ${length}-${first_byte}-${last_byte}; responses shorter than 100 bytes are not cached.
decodeFastQueryBinary(data, kairos = false, useCache = true)clarity:SDK/javascript/clarity-sdk.js:183-249
Decodes the basic binary format — accepts version 1 (f32 values) and version 2 (f64 values); the value width is chosen per header (wide = formatVersion === 2). Rejects any other version.
Binary layout:
Header: [num_tags: u32][format_version: u32 (1 or 2)][reserved: u32]
For each tag:
[tag_name_len: u16][tag_name: utf8]
[num_points: u32]
For each point:
[timestamp: u64][value: f32 (v1) | f64 (v2)]
Per-point value reads dispatch readFloat64()/readFloat32() on the version (clarity:SDK/javascript/clarity-sdk.js:223, 232). Timestamps are read as BigUInt64 and cast to Number.
Returns: { [tagName]: Array<[number, number]> }. If kairos = true: { queries: [...] } with timestamps multiplied by 1000 (milliseconds).
decodeFastQueryOptimised(data, kairos = false, useCache = true)clarity:SDK/javascript/clarity-sdk.js:252-399
Decodes the optimized shared-timestamp format — accepts version 2 (f32 values) and version 3 (f64 values) (wide = formatVersion === 3).
Binary layout:
Header: [num_timestamps: u32][num_tags: u32][format_version: u32 (2 or 3)][reserved: u32]
Shared timestamps: [timestamp: u64] × num_timestamps
For each tag:
[tag_name_len: u16][tag_name: utf8]
Validity bitmap: ceil(num_timestamps / 8) bytes
Non-null values: [value: f32 (v2) | f64 (v3)] for each set bit in bitmap
The shared timestamp block is decoded once; per tag, the validity bitmap is walked to emit [ts, value] for set bits and [ts, null] for clear bits, with value reads dispatched on the version (clarity:SDK/javascript/clarity-sdk.js:323, 331).
Returns: { [tagName]: Array<[number, number | null]> } — null for missing values.
clarity:SDK/javascript/clarity-sdk.js:856-916
When Worker and Blob are available, a WorkerPool of workers is created and attached as OptimizedClarityDecoder.workerPool. Workers receive inlined copies of the reader + decoder via Blob URL. The pool dispatches tasks to idle workers; callers invoke it directly via workerPool.decode(method, data, kairos).
clarity:SDK/javascript/clarity-sdk.js:473-820
High-level HTTP read client. Uses native fetch in browsers; falls back to node-fetch (dynamic import) in Node.js. All query endpoints target /exactapi/….
const client = new OptimizedClarityClient(baseUrl, token, {
cacheSize: 100, // LRU cache entries (default: 100)
cacheTTL: 60000, // Cache TTL ms (default: 60000)
enableCache: true,
parallel: true, // Enable parallel batchQuery (default: true)
});
clarity:SDK/javascript/clarity-sdk.js:474-478
queryBinary_v2({ organization, site, unit, grid, tags, start, end, kairos, downsample, pipeline })clarity:SDK/javascript/clarity-sdk.js:534-621
The primary binary read. Calls POST /exactapi/fast_query_binary and decodes via decodeFastQueryBinary. If Content-Length > 1 MB it streams the response (ReadableStream in the browser, arrayBuffer() in Node.js) before decoding.
Note: the older
queryBinary(...)method is now an empty stub — it takes the same arguments but has no body and returnsundefined(clarity:SDK/javascript/clarity-sdk.js:532-533).queryBinary_v2supersedes it.batchQuery/preloadstill dispatch toqueryBinary/queryOptimisedby name (clarity:SDK/javascript/clarity-sdk.js:784-823), so aformat-less batch entry hits the stub — preferqueryOptimisedor callqueryBinary_v2directly. AqueryBinaryTemp(...)variant also exists (clarity:SDK/javascript/clarity-sdk.js:627).
queryOptimised({ organization, site, unit, grid, tags, start, end, kairos })clarity:SDK/javascript/clarity-sdk.js:723-782
Calls POST /exactapi/fast_query_optimised and decodes via decodeFastQueryOptimised (shared-timestamp + bitmap). Reads the full arrayBuffer() regardless of size.
clarity:SDK/javascript/clarity-sdk.js:784-823
batchQuery(queries, kairos = false) — runs queries in parallel (Promise.all) when parallel: true, else sequentially. Each query may set format: 2 to route to queryOptimised; otherwise it routes to queryBinary (the stub — see note above).clearCache() — clears both the client LRU cache and the static OptimizedClarityDecoder.cache.preload(queries) — fires all queries in parallel, ignoring errors; warms the cache.pipeline is an optional object keyed by tag ID. Each value is an ordered array of aggregation step objects, each with op (string) and optional bucket (milliseconds; default 60000). When pipeline is provided, the request is routed to /exactapi/fast_query (JSON).
clarity:backend/src-tauri/src/api/aggregator.rs:8-34
op string |
Extra fields | Description |
|---|---|---|
"mean" / "avg" |
— | Arithmetic mean per bucket |
"sum" |
— | Sum per bucket |
"min" / "max" |
— | Min / Max per bucket |
"count" |
— | Count of non-null values per bucket |
"first" / "last" |
— | First / last value in bucket |
"dev" |
— | Standard deviation per bucket |
"diff" |
— | Difference between consecutive values |
"gaps" |
bucket (ms, required), query start/end |
Gap-fill resampling |
"percentile" / "histogram" |
percentile (number) |
Nth percentile / histogram per bucket |
"rate" |
unit (string, e.g. "second") |
Rate of change per time unit |
"scale" |
factor (number) |
Multiply all values by factor |
"div" |
divisor (number) |
Divide all values by divisor |
"filter" |
filter_op (lt|lte|gt|gte|equal), threshold |
Retain only values matching the condition |
"leastsquares" |
— | Linear regression fit over the window |
"trim" |
trim: first|last|both |
Remove first, last, or both data points |
"score" |
order: ascending|descending, thresholds |
Maps values to a score index |
"sampler" |
unit (string) |
Placeholder — returns input unchanged |
"saveas" |
metric_name, tags, ttl?, add_saved_from? |
Placeholder — not implemented |
The enum uses #[serde(tag = "op", rename_all = "lowercase")]; parameter sub-enums are lowercase-canonical (UPPERCASE spellings remain valid aliases). Full detail: Storage Engine § Aggregation.
clarity:SDK/javascript/clarity-sdk.js:183-399
| Category | How raised | Condition |
|---|---|---|
| Format validation | throw new Error(...) |
decodeFastQueryBinary: version ∉ {1,2}; decodeFastQueryOptimised: version ∉ |
| HTTP errors | throw new Error("HTTP <status>: <statusText>") |
Any fetch response where response.ok === false |
All raise plain Error instances — no custom subclass hierarchy.
| Optimization | Mechanism |
|---|---|
| Buffer pool | Up to 10 ArrayBuffer instances reused across decode calls; buffers ≤1 MB pooled |
| LRU cache | 100 entries, 60 s TTL; keyed by {tags, start, end, [context]} |
| Connection keep-alive | Node.js http.Agent / https.Agent with maxSockets=10, keepAliveMsecs=30000 |
| Streaming | ReadableStream (browser) for responses > 1 MB in queryBinary_v2 |
| Web Workers | worker pool for parallel binary decoding in browser environments |
Binary format vs JSON: ~5–10× smaller.
clarity:SDK/javascript/clarity-sdk.js:17-23, 176-471
clarity:SDK/javascript/clarity-sdk.js:922-936
// CommonJS
const { ClarityDecoder, ClarityClient } = require('./clarity-sdk');
// ES module
import { ClarityDecoder, ClarityClient } from './clarity-sdk';
OptimizedClarityDecoder and OptimizedClarityClient are also exported directly under their full names.
Last updated: 2026-07-17 from commit 6800acc