Node.js SDK

Use the Node.js SDK from server-side TypeScript or JavaScript applications.

Before you start

Use Node.js 20 or later. Follow Connect an application, then set the endpoint and API key used by the examples:

export SCOPEDB_ENDPOINT="https://<endpoint>"
export SCOPEDB_API_KEY="<api-key>"

Install

pnpm add scopedb

The package is ESM-only. Import it with ES module syntax as shown below.

Create a client

import { Client } from "scopedb";

const endpoint = process.env.SCOPEDB_ENDPOINT;
const apiKey = process.env.SCOPEDB_API_KEY;

if (!endpoint || !apiKey) {
  throw new Error("SCOPEDB_ENDPOINT and SCOPEDB_API_KEY are required");
}

const client = new Client(endpoint, { token: apiKey });

Keep the API key on the server. Do not create authenticated ScopeDB clients in browser code.

Execute a statement

const result = await client
  .statement(`
    FROM events
    WHERE service = 'checkout'
    ORDER BY time DESC
    LIMIT 10
  `)
  .execute();

execute() returns a finished result or throws when execution fails, is cancelled, or the request is aborted. It handles an active statement's polling internally.

Work with results

For most application code, convert rows to objects keyed by column name:

const rows = result.intoObjects();
console.log(rows[0]);

Use first() for a lookup or aggregate that returns at most one row, and intoValues() when positional arrays are more convenient.

Result value mapping

intoValues(), intoObjects(), and first() convert result cells according to their ScopeDB result type:

ScopeDB result typeJavaScript valueNotes
intbigintUse integerMode to return a number or decimal string instead.
uintbigintUse integerMode to return a number or decimal string instead.
floatnumberFinite values only; NaN and infinities cause conversion to throw.
binarystringHexadecimal representation.
stringstring
booleanboolean
timestampDateJavaScript Date preserves milliseconds, not nanoseconds.
intervalstringFixed-duration ISO 8601 representation.
arraystringJSON text; use JSON.parse() when an array is needed.
objectstringJSON text; use JSON.parse() when an object is needed.
anystringRaw textual value; the SDK does not infer its dynamic JavaScript type.
nullnullA null cell is null regardless of the field's declared type.

The null result type can appear in query metadata, such as for a literal NULL; it is not a table column type. See the data types reference for ScopeDB type semantics.

ScopeDB integers can exceed JavaScript's safe integer range. The SDK returns them as bigint by default, which preserves precision but cannot be passed to JSON.stringify directly. Choose the representation at the application boundary:

const jsonSafeRows = result.intoObjects({ integerMode: "string" });

Use:

  • bigint for lossless JavaScript arithmetic;
  • string for JSON-safe identifiers or unbounded counters;
  • number only when values fit within JavaScript's safe integer range.

Converting a timestamp to Date discards sub-millisecond precision. Use jsonRows() when the application must retain the original result text.

array and object values contain JSON text. Do not assume that an any value is JSON: it remains raw text because its dynamic ScopeDB type cannot be reconstructed from the result. When parsing array or object values with JSON.parse(), nested integers outside JavaScript's safe range can lose precision. Parsing structured values does not recursively apply the SDK's result conversions; nested binary, timestamp, and interval values remain strings.

Control statement execution

Use submit() when you need a StatementHandle instead of waiting through execute():

const handle = await client.statement("SELECT 1 AS ok").submit();

console.log(handle.status());
await handle.fetchOnce();
const result = await handle.fetch();

An AbortSignal stops client-side requests and polling; it does not cancel a statement in ScopeDB. Call handle.cancel() to request server-side cancellation. See the HTTP API for the underlying state and cancellation contract.

Ingest data

The current SDK exposes ingestStream() for batching JSON rows that share one ScopeQL transformation. Follow Ingest data for the current write workflow. Reuse a stream for its transformation and always call shutdown() when finished; shutdown() flushes remaining rows, so a preceding flush() is optional.

The helper retries transient failures. A lost response can cause a row to be sent again, so use the retry guidance in the HTTP API.

Next steps