Skip to main content

SDK Server Reference

Complete reference for @zaflun/lumio-sdk/server - the server-side library used in server/functions.ts.

Import​

import { action, query, v } from "@zaflun/lumio-sdk/server";

Defining functions​

Use query() for reads, mutation() for writes, and action() for work with side effects. Export each handler by name from server/functions.ts; the exported name is the function name that your UI passes to useQuery() or useMutation().

import { action, query } from "@zaflun/lumio-sdk/server";

export const getVotes = query({
args: {},
handler: async (ctx) => ctx.db.list("votes"),
});

export const clearVotes = action({
args: {},
handler: async (ctx) => {
const votes = await ctx.db.list("votes");
for (const vote of votes) await ctx.db.delete("votes", vote._id);
return { cleared: votes.length };
},
});

See Handler-based Functions for the execution flow, caller permissions, and limits.

Handler context​

Server-function handlers can use the install-scoped ctx.db, ctx.cache, ctx.secrets, ctx.defer, and ctx.realtime APIs described in Handler-based Functions. A query() handler is read-only: database writes, cache writes, and deferred jobs are refused.

ctx.fetch() refuses every external host in server functions. The manifest's egress.allowHosts does not change this. To call external APIs, use a bot-module handler and declare its egress hosts.

Bot-module handlers use the Bot Module Context. Their ctx.fetch() follows the declared allowlist; their ctx.db requires a version with a declared data schema.


Validation - v​

The v object provides runtime argument validators. All args must be declared with v - undeclared fields are stripped before the handler runs.

// Primitives
v.string()
v.number()
v.boolean()
v.null_()

// Modifiers
v.optional(v.string()) // string | undefined — field may be absent
v.nullable(v.string()) // string | null

// Collections
v.array(v.string())
v.object({ name: v.string(), count: v.number() })

// Union
v.union([v.string(), v.number()])

// Literal
v.literal("active")

Validation happens before the handler is called. Invalid args return a structured error to the caller without invoking the handler.


Exports from server/functions.ts​

Every named export from server/functions.ts that is an action() or query() result is automatically registered with the platform at deploy time. No additional registration step is needed.

// server/functions.ts
export const getScore = query({ ... }); // registered as "getScore"
export const setScore = action({ ... }); // registered as "setScore"

// Not registered — not an action or query
export const MULTIPLIER = 2;

The exported name becomes the actionName / queryName used on the client.


Bot module handlers​

Bot module extensions (category: "bot_module") use a separate set of handler wrappers for chat interaction. Each wrapper sets a __type discriminant on the exported function, following the same pattern as query() and action().

Handler type reference​

Wrapper__type__triggerSync/AsyncTimeout
command(name, handler)"command"Command nameSync500ms
keyword(word, handler)"keyword"Keyword stringAsync10s
pattern(regex, handler)"pattern"Regex stringAsync10s
event(type, handler)"event"Event typeAsync10s
timer(name, handler)"timer"Timer nameAsync10s
moderate(handler)"moderate"N/ASync500ms

Signatures​

function command(
name: string,
handler: (ctx: BotModuleContext, args: string[]) => Promise<HandlerResponse | null>
): CommandDefinition;

function keyword(
word: string,
handler: (ctx: BotModuleContext, message: ChatMessage) => Promise<HandlerResponse | null>
): KeywordDefinition;

function pattern(
regex: string,
handler: (ctx: BotModuleContext, message: ChatMessage, matched: string) => Promise<HandlerResponse | null>
): PatternDefinition;

function event(
eventType: string,
handler: (ctx: BotModuleContext, evt: Record<string, unknown>) => Promise<HandlerResponse | null>
): EventDefinition;

function timer(
name: string,
handler: (ctx: BotModuleContext) => Promise<HandlerResponse | null>
): TimerDefinition;

function moderate(
handler: (ctx: BotModuleContext, message: ChatMessage) => Promise<ModerationResponse>
): ModerateDefinition;

BotModuleContext​

See Bot Module Context for the full API reference. In bot-module handlers ctx.cache, ctx.secrets, ctx.fetch and ctx.defer() work; ctx.db requires a version with a declared data schema.

HandlerResponse​

interface HandlerResponse {
reply?: string;
actions?: ActionRequest[];
}

interface ActionRequest {
action: string;
params: Record<string, unknown>;
}

ModerationResponse​

interface ModerationResponse {
block: boolean;
action?: "delete" | "timeout" | "ban";
duration?: number;
reason?: string;
}

// defineModerate(handler) return value
interface ModerateResult {
action: "allow" | "delete" | "timeout" | "warn" | "ban";
duration?: number;
reason?: string;
message?: string;
}

Lumio acts on the action field only. allow (or no action) lets the message through; delete, timeout, ban and warn become the chat actions chat:delete, chat:timeout (duration seconds, default 600), chat:ban and chat:send (message, else reason). The manifest must declare that action in permissions, or it is refused. block is not read: { block: true } without an action does nothing. The handler has a 500ms budget; a timeout or error lets the message through. See Bot Modules → Moderation.

ChatMessage​

interface ChatMessage {
text: string;
platformMessageId: string;
}