Utilities
The JavaScript SDK provides a set of utility functions for common tasks like deep value comparison, JSON conversion, SurrealQL string serialization, identifier escaping, and expression building. These complement the SDK’s core query methods and value types.
API References
Comparing values with deep equality
JavaScript’s === operator compares objects by reference, which means two RecordId instances with the same table and ID are not considered equal. The equals() function performs deep structural comparison across all value types, including SurrealDB’s custom classes, nested objects, arrays, Date, RegExp, and bigint/number normalization.
import { equals, RecordId } from 'surrealdb';
const id1 = new RecordId('users', 'john');
const id2 = new RecordId('users', 'john');
console.log(id1 === id2);
console.log(equals(id1, id2));
This is particularly useful for detecting changes in query results.
const user1 = await db.select(userId);
const user2 = await db.select(userId);
if (!equals(user1, user2)) {
console.log('Record was modified');
}
Individual value classes also expose an .equals() instance method for single-type comparisons (e.g. recordId.equals(other)). Use the standalone equals() function for generic or cross-type comparisons.
Jsonifying query results
The jsonify() function converts SurrealDB value types in a result to their JSON representations, in the same manner that SurrealDB would serialize them. It only transforms SurrealDB-specific classes, leaving all other values untouched, and is fully type-safe.
import { jsonify, RecordId, Decimal, Duration } from 'surrealdb';
const result = jsonify({
rid: new RecordId('person', 'tobie'),
dec: new Decimal('3.333333'),
dur: new Duration('1d2h'),
num: 123,
str: 'hello',
});
{
"rid": "person:tobie",
"dec": "3.333333",
"dur": "1d2h",
"num": 123,
"str": "hello"
}
You can also jsonify query results directly using the .json() chain on query methods.
Building expressions
The expr() function and its companion operators allow you to compose dynamic, type-safe conditions for use in query builder methods like .where() and in surql templates. See Bound queries for the full guide.
import { expr, surql, eq, gte, and, Table } from 'surrealdb';
const premiumAdults = expr(and(
eq('tier', 'premium'),
gte('age', 18),
));
const users = await db.select(new Table('users')).where(premiumAdults);
Available operators include comparison (eq, ne, gt, gte, lt, lte), logical (and, or, not), string/array (contains, containsAny, containsAll), geometry (inside, outside, intersects), and search (matches, knn).
Composing parameterized queries
The surql tagged template and BoundQuery class provide safe parameterization for dynamic queries. See Bound queries for the full guide.
import { surql, BoundQuery } from 'surrealdb';
const minAge = 18;
const query = surql`SELECT * FROM users WHERE age >= ${minAge}`;
const [users] = await db.query(query);
const bound = new BoundQuery(
'SELECT * FROM users WHERE status = $status',
{ status: 'active' },
);
bound.bind('tier', 'premium');
const [results] = await db.query(bound);
Escaping identifiers and values
When you need to construct SurrealQL strings manually, the escape functions ensure that identifiers and values are properly quoted. In most cases, you should prefer bound queries or the value type classes instead of manual escaping.
import { escapeIdent, escapeKey, escapeRid, escapeValue } from 'surrealdb';
escapeIdent('users');
escapeIdent('user-table');
escapeIdent('select');
escapeKey('user-property');
escapeRid('john');
escapeRid('user@email.com');
escapeValue('hello');
escapeValue(42);
escapeValue(null);
escapeValue(undefined);
Escape functions are not a complete defense against injection. Always prefer parameterized queries using surql or BoundQuery.
Best practices
Use surql for parameterization
const query = surql`SELECT * FROM users WHERE name = ${userName}`;
const query = `SELECT * FROM users WHERE name = '${userName}'`;
Use expr for complex conditions
const condition = expr(and(
eq('status', 'active'),
gte('age', 18),
));
await db.select(new Table('users')).where(condition);
Use equals for deep comparison
if (equals(recordId1, recordId2)) {
}
if (recordId1 === recordId2) { ... }
Learn more