Declarative Functions
Declarative server functions are defined with queryRows, insertRow, patchRow, and deleteRow. They translate directly to parameterized SQL at compile time - no V8 isolate, minimal overhead.
Each definition is plain data. lumio build evaluates server/functions.ts and writes every export, under its name, to dist/functions.json (the functions manifest), which lumio deploy uploads with the version. The build fails on an export that is not a function definition, a value that is not plain JSON, or a table server/schema.ts does not declare. Lumio checks the manifest again at upload, and at call time looks the function up by name in the manifest of the version the install runs: the client only sends the name and the arg() values.
When to use declarative
Use declarative functions for standard CRUD operations on tables defined in your schema. For complex business logic, aggregations, or external API calls, use handler-based functions instead.
Basic example
// server/functions.ts
import { queryRows, insertRow, patchRow, deleteRow, arg } from "@zaflun/lumio-sdk/server";
// List all rules
export const getRules = queryRows("rules");
// Add a new rule (editor only — streamers only, not viewers)
export const addRule = insertRow("rules", {
text: arg("text"),
revealed: false,
}, { editorOnly: true });
// Reveal a rule
export const revealRule = patchRow("rules", arg("id"), {
revealed: true,
}, { editorOnly: true });
// Delete a rule
export const deleteRule = deleteRow("rules", arg("id"), { editorOnly: true });
queryRows
Returns the rows of a table, ordered by created_at ASC unless you set orderBy, at most 100 unless you set limit (clamped to 1000). Each row is the full row as JSON, including the system columns _id, _created_at and _updated_at.
queryRows(tableName: string, options?: QueryRowsOptions): QueryRowsDefinition
Options
| Option | Type | Description |
|---|---|---|
filter | FilterExpression | FilterExpression[] | Condition to filter rows; with a list, every condition must match |
orderBy | string | Column name to sort by (default: "created_at"; "id", "created_at" and "updated_at" name the system columns) |
orderDir | "asc" | "desc" | Sort direction (default: "asc") |
limit | number | ArgExpression | Maximum rows to return (a non-negative integer or arg()) |
offset | number | ArgExpression | Rows to skip (for pagination) |
Options you do not set are left out of the definition. QueryRowsOptions, QueryRowsDefinition, FilterExpression, FilterOperator and ArgExpression are exported from @zaflun/lumio-sdk/server.
// List only revealed rules, newest first
export const getRevealedRules = queryRows("rules", {
filter: filter("revealed", "=", true),
orderBy: "created_at",
orderDir: "desc",
});
// Paginated rules
export const getRulesPaged = queryRows("rules", {
limit: arg("limit"),
offset: arg("offset"),
});
insertRow
Inserts a new row into a table. Returns the inserted row including its generated id and created_at.
insertRow(tableName: string, data: DataObject, options?: InsertRowOptions): InsertRowDefinition
DataObject
A record of field names to plain JSON values, arg() references or identity() (the caller's identity, resolved server-side). secret() is not allowed here - read secrets in an action() handler:
export const addRule = insertRow("rules", {
text: arg("text"), // value comes from caller: addRule({ text: "..." })
revealed: false, // static value
category: arg("category"), // optional dynamic value
});
patchRow
Updates specific fields of an existing row. The first arg() or value after tableName is the row id.
patchRow(tableName: string, id: string | ArgExpression, data: DataObject, options?: PatchRowOptions): PatchRowDefinition
// Reveal a specific rule
export const revealRule = patchRow("rules", arg("id"), {
revealed: true,
});
// Update multiple fields
export const updateRule = patchRow("rules", arg("id"), {
text: arg("text"),
category: arg("category"),
});
deleteRow
Deletes a row by its id.
deleteRow(tableName: string, id: string | ArgExpression, options?: DeleteRowOptions): DeleteRowDefinition
export const deleteRule = deleteRow("rules", arg("id"), { editorOnly: true });
arg()
The arg() helper marks a field as a dynamic parameter supplied by the caller at runtime:
import { insertRow, arg } from "@zaflun/lumio-sdk/server";
export const addVote = insertRow("votes", {
choice: arg("choice"), // caller provides: castVote({ choice: "yes" })
userId: arg("userId"), // caller provides: castVote({ userId: "..." })
weight: 1, // static value
});
arg("name") is substituted with a SQL $n parameter placeholder - preventing SQL injection. The value is checked against the column type (invalid value for column ... otherwise). A value the definition fixes (weight: 1) cannot be overridden by the caller. A missing arg() becomes null in row values and filters (accepted only for optional columns), is ignored for limit / offset, and is an error for a row id (missing argument `id` ).
filter()
Build filter conditions for queryRows. filter(field, op, value) is typed: op is a FilterOperator, and an unsupported operator also fails lumio build.
import { filter, arg } from "@zaflun/lumio-sdk/server";
// Static filter
export const getRevealedRules = queryRows("rules", {
filter: filter("revealed", "=", true),
});
// Dynamic filter (value from caller)
export const getRulesByCategory = queryRows("rules", {
filter: filter("category", "=", arg("category")),
});
Supported operators
| Operator | SQL equivalent |
|---|---|
"=" | = |
"!=" | <> |
">" | > |
">=" | >= |
"<" | < |
"<=" | <= |
"like" | LIKE |
"in" | = ANY(...) |
editorOnly option
Functions with editorOnly: true can only be called from the editor surface - the Lumio dashboard, where the streamer is signed in. Calls from the extension running in an OBS overlay or widget are rejected with Editor-only function called outside editor. The surface comes from the host's credential, not from your extension (see Auth and Scopes):
export const deleteRule = deleteRow("rules", arg("id"), {
editorOnly: true, // only the streamer/editor can delete
});
Use this for admin operations that only the streamer should perform.