RunPromise<T, J>

The RunPromise class provides an interface for executing SurrealDB functions and SurrealML models. It extends Promise, allowing you to await it directly or use configuration methods.

Returned by: SurrealQueryable.run()

Source: query/run.ts

Type Parameters

  • T - The return type of the function

  • J - Boolean indicating if result is JSON (default: false)

Configuration Methods

.json()

Configure the query to return the result as a JSON string.

Method Syntax

runPromise.json()

Returns

RunPromise<T, true> - Promise returning JSON string

Example

const jsonResult = await db.run('fn::calculate', [10, 20]).json();
console.log(typeof jsonResult); // 'string'

.stream()

Stream the function result.

Method Syntax

runPromise.stream()

Returns

AsyncIterableIterator<Frame<T, J>> - Async iterator

Complete Examples

Built-in Functions

import { Surreal } from 'surrealdb';

const db = new Surreal();
await db.connect('ws://localhost:8000');

// Time functions
const now = await db.run('time::now');
console.log('Current time:', now);

const timestamp = await db.run('time::unix');
console.log('Unix timestamp:', timestamp);

// Array functions
const unique = await db.run('array::distinct', [[1, 2, 2, 3, 3, 3]]);
console.log('Unique values:', unique); // [1, 2, 3]

// String functions
const upper = await db.run('string::uppercase', ['hello world']);
console.log(upper); // 'HELLO WORLD'

// Math functions
const rounded = await db.run('math::round', [3.14159]);
console.log(rounded); // 3

// Crypto functions
const hash = await db.run('crypto::md5', ['password123']);
console.log('Hash:', hash);

Custom Functions

// First, define a custom function in SurrealDB
await db.query(`
DEFINE FUNCTION fn::calculate_total($items: array) {
RETURN array::sum($items.map(|$item| $item.price * $item.quantity));
};
`).collect();

// Then call it
const items = [
{ price: 10, quantity: 2 },
{ price: 5, quantity: 3 }
];

const total = await db.run('fn::calculate_total', [items]);
console.log('Total:', total); // 35

SurrealML Models

// Run a machine learning model
const prediction = await db.run(
'ml::predict_sentiment',
'1.0.0', // Model version
['This is a great product!']
);

console.log('Sentiment:', prediction);

With Type Safety

interface CalculationResult {
sum: number;
average: number;
count: number;
}

const result = await db.run<CalculationResult>(
'fn::calculate_stats',
[[10, 20, 30, 40, 50]]
);

console.log('Sum:', result.sum);
console.log('Average:', result.average);
console.log('Count:', result.count);

Complex Function Arguments

// Function with multiple arguments
const result = await db.run('fn::process_order', [
new RecordId('users', 'john'),
new RecordId('products', 'widget'),
{
quantity: 5,
shipping_address: '123 Main St',
payment_method: 'credit_card'
}
]);

Parameterized Functions

// Function that uses session variables
await db.set('discount_rate', 0.1);

const total = await db.run('fn::calculate_price', [
100, // base price
// Function can access $discount_rate
]);

Error Handling

try {
const result = await db.run('fn::risky_operation', [data]);
} catch (error) {
if (error instanceof ResponseError) {
console.error('Function failed:', error.message);
}
}

Batch Function Calls

const results = await db.query(`
RETURN fn::process(${data1});
RETURN fn::process(${data2});
RETURN fn::process(${data3});
`).collect();

console.log('Batch results:', results);

With Transaction

const txn = await db.beginTransaction();

try {
// Call function within transaction
const result = await txn.run('fn::allocate_inventory', [
new RecordId('products', 'widget'),
10
]);

// Other transaction operations
await txn.create(new Table('orders')).content({
product: result.product,
allocated: result.quantity
});

await txn.commit();
} catch (error) {
await txn.cancel();
}

Scheduled Functions

// Define a scheduled function
await db.query(`
DEFINE FUNCTION fn::cleanup_old_records() {
DELETE FROM logs WHERE created_at < time::now() - 30d;
};
`).collect();

// Run manually
await db.run('fn::cleanup_old_records');

Recursive Functions

await db.query(`
DEFINE FUNCTION fn::factorial($n: number) {
IF $n <= 1 THEN
RETURN 1
ELSE
RETURN $n * fn::factorial($n - 1)
END
};
`).collect();

const result = await db.run('fn::factorial', [5]);
console.log('5! =', result); // 120

Data Transformation

// Define transformation function
await db.query(`
DEFINE FUNCTION fn::format_user($user: record) {
RETURN {
full_name: string::concat($user.first_name, ' ', $user.last_name),
email: string::lowercase($user.email),
age: time::year(time::now()) - time::year($user.birth_date)
};
};
`).collect();

// Use it
const user = await db.select(new RecordId('users', 'john'));
const formatted = await db.run('fn::format_user', [user]);
console.log(formatted);

ML Model Versions

// Run specific model version
const v1Result = await db.run('ml::classify_image', '1.0.0', [imageData]);
const v2Result = await db.run('ml::classify_image', '2.0.0', [imageData]);

console.log('v1 prediction:', v1Result);
console.log('v2 prediction:', v2Result);

Validation Functions

await db.query(`
DEFINE FUNCTION fn::validate_email($email: string) {
RETURN string::is::email($email);
};
`).collect();

const isValid = await db.run('fn::validate_email', ['user@example.com']);

if (isValid) {
// Proceed with user creation
}

Best Practices

1. Type Function Results

// Good: Type the result
interface Stats {
count: number;
average: number;
}

const stats = await db.run<Stats>('fn::calculate_stats', [data]);
stats.count; // TypeScript knows this exists

// Avoid: Untyped
const stats = await db.run('fn::calculate_stats', [data]);
stats.count; // No type safety

2. Handle Function Errors

// Good: Handle errors
try {
const result = await db.run('fn::risky_operation', [data]);
} catch (error) {
console.error('Function failed:', error);
}

// Consider: Implement error handling in the function itself
await db.query(`
DEFINE FUNCTION fn::safe_operation($data: any) {
TRY {
RETURN fn::risky_operation($data);
} CATCH {
RETURN { error: true, message: 'Operation failed' };
}
};
`).collect();

3. Validate Function Names

Function names must follow the pattern: namespace::function_name

// Good: Valid function names
await db.run('fn::my_function', []);
await db.run('custom::calculate', []);
await db.run('ml::predict', '1.0.0', []);

// Invalid: Will throw error
await db.run('invalid name', []); // No namespace
await db.run('fn:bad-name', []); // Invalid characters

See Also