Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nickruigrok/baseflare/llms.txt
Use this file to discover all available pages before exploring further.
ctx.db.query(table) returns a QueryBuilder. You chain filter, order, and limit methods on it, then terminate the chain with a collector method such as .collect(), .first(), or .paginate(). Under the hood the builder compiles your filter object into a parameterized SQLite WHERE clause using json_extract() expressions, submits it to D1, deserializes the rows, and runs them through your read permission rule before returning results to the handler.
createQueryBuilder(tableName, executor?)
createQueryBuilder is also exported from baseflare/server for direct use in utilities or tests. It accepts an optional executor argument that connects the builder to a real database. Without one, the builder exposes additional .toSQL() and .toCountSQL() methods for SQL inspection but throws if you call any terminal collector method.
A
QueryBuilder created via createQueryBuilder without an executor is not
connected to a database. Calling .collect() or other terminal methods on it
will throw. This variant is intended for SQL inspection and unit tests. Permission
rules are not applied by the standalone builder — they are enforced at the runtime
layer inside ctx.db.query().Chaining Methods
All chaining methods return a newQueryBuilder — the original is never mutated and can be branched and reused.
.filter(filterObject)
Adds filter conditions. Multiple .filter() calls are ANDed together. See the FilterObject format section for the full filter syntax.
.order(direction)
Order results by _id (which encodes creation time), ascending or descending.
.order(field, direction)
Order results by a specific document field. When ordering by a user field, a secondary ORDER BY _id tiebreaker is appended automatically to guarantee stable pagination. Passing '_id' or '_createdAt' as the field name orders by the row’s primary key.
.limit(n)
Cap the maximum number of rows returned. Must be a non-negative integer.
Collector Methods
Collector methods execute the query and return results. They require a live database executor (i.e. aQueryBuilder obtained from ctx.db.query()).
.collect()
Fetch all documents matching the current query state. Permission rules are applied row-by-row; documents that fail the read rule are filtered out silently.
.first()
Return the first matching document, or null if none exist. Internally applies .limit(1) before executing.
.unique()
Return exactly one matching document. Throws a ValidationError if zero or two or more documents are returned. Useful when you expect a uniqueness constraint and want an explicit failure instead of a silent empty result.
.take(n)
Shorthand for .limit(n).collect().
.count()
Return the number of documents matching the current filter. When called through ctx.db.query() inside a server function, only documents that pass the read permission rule are counted — the runtime scans results through the rule before tallying. When called on a standalone builder created with createQueryBuilder, no permission filtering is applied.
.paginate(options)
Cursor-based pagination. Returns a page of results plus a continuation cursor.
Number of items per page. Must be a positive integer.
Opaque cursor string from a previous
.paginate() call. Omit or pass undefined
to start from the beginning.The documents for this page.
true when there are no more pages after this one.Opaque cursor to pass as
options.cursor in the next call.FilterObject Format
A FilterObject is a plain object where keys are field names and values describe the match condition.
Equality
Comparison operators
Use an object value to apply comparison operators. Supported operators:eq, neq, gt, gte, lt, lte, in.
_createdAt range filters
_createdAt supports only gt, gte, lt, lte with millisecond epoch timestamps. Equality (eq, neq, in) is not supported.
Logical combinators
AND, OR, and NOT allow composing multiple filter objects:
SQLite’s query planner automatically selects the best index based on your
filter conditions. You never need to hint which index to use — Baseflare
never exposes index selection to the application layer.