SurrealDB
SurrealDB Docs Logo

Enter a search query

Navigation

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