@ydbjs/query
The @ydbjs/query
package provides a high-level, type-safe client for executing YQL queries and managing transactions in YDB. It features a tagged template API, automatic parameter binding, transaction helpers, and deep integration with the YDB type system.
Features
- Tagged template syntax for YQL queries
- Type-safe, automatic parameter binding (including complex/nested types)
- Transaction helpers with isolation and idempotency options
- Multiple result sets and streaming support
- Query statistics and diagnostics
- Full TypeScript support
Installation
npm install @ydbjs/core@alpha @ydbjs/query@alpha
How It Works
- Query Client: Create a query client with
query(driver)
. This provides a tagged template function for YQL queries and helpers for transactions.
- Sessions & Transactions: Sessions and transactions are managed automatically. You can run single queries or group multiple queries in a transaction with
begin
/transaction
.
- Parameter Binding: Parameters are bound by interpolation (
${}
) in the template string. Native JS types, YDB value classes, and arrays/objects are all supported. Use .parameter()
/.param()
for named parameters.
- Type Safety: All values are converted using
@ydbjs/value
(see its docs for details). Complex/nested types and arrays are handled automatically.
- Result Sets: Most queries return an array of result sets (YDB supports multiple result sets per query).
- Query Statistics: Use
.withStats()
or .stats()
to access execution statistics.
Usage
Quick Start
import { Driver } from '@ydbjs/core'
import { query } from '@ydbjs/query'
const driver = new Driver('grpc://localhost:2136/local')
await driver.ready()
const sql = query(driver)
const resultSets = await sql`SELECT 1 + 1 AS sum`
console.log(resultSets)
Parameterized Queries
const userId = 42n
const userName = 'Alice'
await sql`
SELECT * FROM users
WHERE id = ${userId} AND name = ${userName}
`
Named Parameters and Custom Types
import { Uint64 } from '@ydbjs/value/primitive'
const id = new Uint64(123n)
await sql`SELECT * FROM users WHERE id = $id`.parameter('id', id)
Arrays, Structs, and Table Parameters
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
]
await sql`INSERT INTO users SELECT * FROM AS_TABLE(${users})`
Transactions
const result = await sql.begin(async (tx) => {
await tx`UPDATE users SET active = false WHERE last_login < CurrentUtcTimestamp() - Interval('P1Y')`
return await tx`SELECT * FROM users WHERE active = false`
})
await sql.begin({ isolation: 'snapshotReadOnly', idempotent: true }, async (tx) => {
return await tx`SELECT COUNT(*) FROM users`
})
Advanced: Multiple Result Sets, Streaming, and Events
type Result = [[{ id: number }], [{ count: number }]]
const [rows, [{ count }]] = await sql<Result>`SELECT id FROM users; SELECT COUNT(*) as count FROM users;`
const q = sql`SELECT * FROM users`.withStats(StatsMode.FULL)
q.on('stats', (stats) => console.log('Query stats:', stats))
q.on('retry', (ctx) => console.log('Retrying:', ctx))
await q
Error Handling
import { YDBError } from '@ydbjs/error'
try {
await sql`SELECT * FROM non_existent_table`
} catch (e) {
if (e instanceof YDBError) {
console.error('YDB Error:', e.message)
}
}
Query Options and Chaining
await sql`SELECT * FROM users`
.isolation('onlineReadOnly', { allowInconsistentReads: true })
.idempotent(true)
.timeout(5000)
.withStats(StatsMode.FULL)
Value Conversion and Type Safety
All parameter values are converted using @ydbjs/value
. See its documentation for details on supported types and conversion rules. You can pass native JS types, or use explicit YDB value classes for full control.
import { fromJs } from '@ydbjs/value'
await sql`SELECT * FROM users WHERE meta = ${fromJs({ foo: 'bar' })}`
Query Statistics
You can enable and access query execution statistics:
const q = sql`SELECT * FROM users`.withStats(StatsMode.FULL)
await q
console.log(q.stats())
Development
Building the Package
npm run build
Running Tests
npm test
AI Assistant Configuration
This package includes example configuration files for AI assistants to generate secure YQL code in the ai-instructions/
directory:
Available Examples:
ai-instructions/.cursorrules.example
- Cursor AI (legacy format)
ai-instructions/.instructions.example.md
- General AI assistants
ai-instructions/.ai-instructions.example.md
- Alternative general format
ai-instructions/.copilot-instructions.example.md
- GitHub Copilot specific
Copy the appropriate file to your project root (remove .example
suffix) to ensure AI-generated code follows YDB security best practices.
Quick setup:
cp node_modules/@ydbjs/query/ai-instructions/.cursorrules.example .cursorrules
cp node_modules/@ydbjs/query/ai-instructions/.instructions.example.md .instructions.md
See SECURITY.md
for complete security guidelines.
License
This project is licensed under the Apache 2.0 License.
Links