JavaScript: Database and documents
Run SQL with bound parameters, manage documents in collections, tables, migrations and multi-request transactions with @sovaria/sdk.
sovaria.data is your project's Postgres database and its document collections. Every call runs as the client's current user, so access policies and row-level security decide what each query may see and change.
import { createClient } from '@sovaria/sdk'
const sovaria = createClient('https://<project-ref>.sovaria.in', '<anon-key>')
const { columns, rows } = await sovaria.data.sql(
'select id, title from books where author_id = $1 order by title limit $2',
[authorId, 20],
)SQL
sovaria.data.sql
Run one SQL statement.
sovaria.data.sql(
sql: string,
params?: JsonValue[] | number,
txid?: number = 0,
): Promise<JsonObject>Pass values for $1, $2, … as params — they are bound by the database, so user input never becomes SQL: sql('SELECT * FROM books WHERE id = $1', [id]). A number as the second argument is still read as txid (older signature).
Parameters
sqlstringrequired- One statement:
SELECT,INSERT,UPDATE,DELETEorEXPLAIN. Schema changes belong in migrations. paramsJsonValue[] | numberoptional- Values for
$1,$2, … in order. txidnumberoptionaldefault0- Run inside a transaction from
beginTransaction().
- Returns
Promise<JsonObject>—{ columns, rows, row_count }—rowsis an array of arrays incolumnsorder.- HTTP
POST /api/v1/sql/query
- App code that sends
CREATE/ALTER/DROPgets400 SQL_ROUTE_VIOLATION. - A table without an access policy and without forced RLS answers
403 … NO_POLICY_DEFINED— see Row-level security and access.
const { rows: [[id]] } = await sovaria.data.sql(
'insert into notes (body) values ($1) returning id',
['Buy milk'],
)Documents
sovaria.data.docPut
Doc put.
sovaria.data.docPut(
collection: string,
documentId: string,
data: JsonObject,
): Promise<JsonObject>Parameters
collectionstringrequired- Collection name (created on first write).
documentIdstringrequired- Your id for the document.
dataJsonObjectrequired- Any JSON object; replaces the whole document.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/doc/{…}/{…}
await sovaria.data.docPut('carts', userId, { items: [{ sku: 'B-12', qty: 2 }] })sovaria.data.docGet
Doc get.
sovaria.data.docGet(
collection: string,
documentId: string,
atTxid?: number,
): Promise<JsonObject>Parameters
collectionstringrequired- Collection name.
documentIdstringrequired- Document id.
atTxidnumberoptional- Read the document as it was at an earlier transaction id.
- Returns
Promise<JsonObject>— The document, or a404SovariaErrorwhen it doesn't exist.- HTTP
GET /api/v1/data/doc/{…}/{…}
sovaria.data.docList
List the documents in one collection (newest writes last): [{ id, data, txid }].
sovaria.data.docList(
collection: string,
options?: { limit?: number } = {},
): Promise<{ id: string; data: JsonObject; txid: number; }[]>Subcollections are not included — list collection/<docId>/<sub> for those.
Parameters
collectionstringrequired- Collection name.
options{ limit?: number }optionaldefault{}limit: how many to return.
- Returns
Promise<{ id: string; data: JsonObject; txid: number; }[]>—[{ id, data }].- HTTP
POST /api/v1/data/query/scan
sovaria.data.docScan
Doc scan.
sovaria.data.docScan(
args: { prefix?: string start_key?: string end_key?: string limit?: number },
): Promise<JsonObject>Parameters
args{ prefix?: string start_key?: string end_key?: string limit?: number }required
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/query/scan
sovaria.data.docDelete
Doc delete.
sovaria.data.docDelete(collection: string, documentId: string): Promise<JsonObject>Parameters
collectionstringrequired- Collection name.
documentIdstringrequired- Document id.
- Returns
Promise<JsonObject>
sovaria.data.putDocumentE2ee
Encrypt client-side and write a Zero-Knowledge document envelope to Atlas-Doc.
sovaria.data.putDocumentE2ee(
collection: string,
documentId: string,
plaintext: Uint8Array | string,
password?: string,
): Promise<JsonObject>Parameters
collectionstringrequireddocumentIdstringrequiredplaintextUint8Array | stringrequired- What to encrypt; it never leaves the device unencrypted.
passwordstringoptional- Encryption password; without it the key from the user's session is used.
- Returns
Promise<JsonObject>
- Sovaria stores only the encrypted envelope. Losing the password means losing the data.
sovaria.data.getDocumentE2ee
Retrieve and decrypt a Zero-Knowledge document from Atlas-Doc.
sovaria.data.getDocumentE2ee(
collection: string,
documentId: string,
password?: string,
atTxid?: number,
): Promise<{ plaintext: Uint8Array<ArrayBufferLike>; }>Parameters
collectionstringrequireddocumentIdstringrequiredpasswordstringoptionalatTxidnumberoptional
- Returns
Promise<{ plaintext: Uint8Array<ArrayBufferLike>; }>
Migrations
sovaria.data.tableMigrations
Table migrations.
sovaria.data.tableMigrations(
query?: { table_name?: string limit?: number offset?: number },
): Promise<JsonObject>Parameters
query{ table_name?: string limit?: number offset?: number }optional- Filter by
table_name; page withlimit/offset.
- Returns
Promise<JsonObject>- HTTP
GET /api/v1/data/rel/migrations
sovaria.data.dryRunMigration
Run a migration inside a transaction and roll it back: reports whether it would apply.
sovaria.data.dryRunMigration(
migration: { name: string; upSql: string; downSql?: string },
): Promise<JsonObject>Parameters
migration{ name: string; upSql: string; downSql?: string }required
- Returns
Promise<JsonObject>— Whether it would succeed, without changing anything (the transaction is rolled back).- HTTP
POST /api/v1/data/rel/migrations/dry-run
sovaria.data.applyMigration
Apply a migration atomically and record it in the project's history.
sovaria.data.applyMigration(
migration: { name: string; upSql: string; downSql?: string; version?: string },
): Promise<JsonObject>downSql makes it reversible.
Parameters
migration{ name: string; upSql: string; downSql?: string; version?: string }requiredname(unique),upSql, optionaldownSql(needed to undo it), optionalversion.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/migrations/apply
- With Staging first on, apply migrations in the staging environment and use Deploy to production — see Environments, staging and deploying to production.
const migration = {
name: '20261016_add_note',
upSql: 'alter table books add column note text',
downSql: 'alter table books drop column note',
}
const check = await sovaria.data.dryRunMigration(migration) // runs and rolls back
await sovaria.data.applyMigration(migration)sovaria.data.rollbackMigration
Undo the latest migration (or version with force) using its down SQL.
sovaria.data.rollbackMigration(
opts?: { version?: string; force?: boolean } = {},
): Promise<JsonObject>Parameters
opts{ version?: string; force?: boolean }optionaldefault{}versionto undo a specific migration (withforce); default the latest.
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/migrations/rollback
- Needs the migration's down SQL.
Tables
sovaria.data.tableCreate
Table create.
sovaria.data.tableCreate(payload: JsonObject): Promise<JsonObject>Parameters
payloadJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/create
sovaria.data.tableDrop
Table drop.
sovaria.data.tableDrop(tableName: string): Promise<JsonObject>Parameters
tableNamestringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/drop
sovaria.data.tableAddColumn
Table add column.
sovaria.data.tableAddColumn(payload: JsonObject): Promise<JsonObject>Parameters
payloadJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/column/add
sovaria.data.tableDropColumn
Table drop column.
sovaria.data.tableDropColumn(tableName: string, columnName: string): Promise<JsonObject>Parameters
tableNamestringrequiredcolumnNamestringrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/column/drop
sovaria.data.tableAddForeignKey
Table add foreign key.
sovaria.data.tableAddForeignKey(payload: JsonObject): Promise<JsonObject>Parameters
payloadJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/foreign-key/add
sovaria.data.tableDropForeignKey
Table drop foreign key.
sovaria.data.tableDropForeignKey(payload: JsonObject): Promise<JsonObject>Parameters
payloadJsonObjectrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/foreign-key/drop
Transactions
sovaria.data.beginTransaction
Begin transaction.
sovaria.data.beginTransaction(): Promise<JsonObject>- Returns
Promise<JsonObject>—{ txid }to pass tosql(…, params, txid), thencommitTransaction(txid)orrollbackTransaction(txid).- HTTP
POST /api/v1/data/rel/transaction/begin
const { txid } = await sovaria.data.beginTransaction()
try {
await sovaria.data.sql('update accounts set balance = balance - $1 where id = $2', [10, from], txid)
await sovaria.data.sql('update accounts set balance = balance + $1 where id = $2', [10, to], txid)
await sovaria.data.commitTransaction(txid)
} catch (err) {
await sovaria.data.rollbackTransaction(txid)
throw err
}sovaria.data.commitTransaction
Commit transaction.
sovaria.data.commitTransaction(txid: number): Promise<JsonObject>Parameters
txidnumberrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/transaction/commit
sovaria.data.rollbackTransaction
Rollback transaction.
sovaria.data.rollbackTransaction(txid: number): Promise<JsonObject>Parameters
txidnumberrequired
- Returns
Promise<JsonObject>- HTTP
POST /api/v1/data/rel/transaction/rollback