Skip to main content

Overview

Queries are read-only functions that fetch data from the Convex database. They automatically update in real-time when the underlying data changes.

Users

current

Get the currently authenticated user’s profile. Location: convex/users.ts:16
export const current = query({
  args: {},
  returns: v.union(userValidator, v.null()),
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) {
      return null;
    }
    return await ctx.db.get(userId);
  },
});

Arguments

No arguments required.

Returns

user
object | null
The current user object or null if not authenticated
_id
Id<'users'>
User’s unique identifier
_creationTime
number
Timestamp when user was created
name
string
User’s display name
email
string
User’s email address
image
string
URL to user’s profile image
emailVerificationTime
number
Timestamp when email was verified
isAnonymous
boolean
Whether this is an anonymous user

Example

const user = await ctx.runQuery(api.users.current);
if (user) {
  console.log(`Logged in as ${user.name}`);
}

get

Get a user’s public profile by ID. Location: convex/users.ts:35
export const get = query({
  args: { userId: v.id("users") },
  returns: v.union(publicProfileValidator, v.null()),
  handler: async (ctx, args) => {
    const user = await ctx.db.get(args.userId);
    if (!user) {
      return null;
    }
    return {
      _id: user._id,
      name: user.name,
      image: user.image,
    };
  },
});

Arguments

userId
Id<'users'>
required
The ID of the user to fetch

Returns

profile
object | null
Public profile information or null if user not found
_id
Id<'users'>
User’s unique identifier
name
string
User’s display name
image
string
URL to user’s profile image

Example

const profile = await ctx.runQuery(api.users.get, {
  userId: "j97abc123..."
});
console.log(profile?.name); // "Alice"

Notes

  • Only returns public fields (excludes email and emailVerificationTime)
  • Returns null if user doesn’t exist

Messages

list

Get all messages in a chat room, ordered chronologically. Location: convex/messages.ts:15
export const list = query({
  args: { roomId: v.string() },
  returns: v.array(messageValidator),
  handler: async (ctx, args) => {
    return await ctx.db
      .query("messages")
      .withIndex("by_room", (q) => q.eq("roomId", args.roomId))
      .order("asc")
      .collect();
  },
});

Arguments

roomId
string
required
The room/channel identifier to fetch messages from

Returns

messages
array
Array of message objects ordered by creation time (oldest first)
_id
Id<'messages'>
Message unique identifier
_creationTime
number
Timestamp when message was created
roomId
string
Room/channel identifier
userId
Id<'users'>
ID of user who sent the message (optional for demo mode)
content
string
Message text content
userName
string
Display name of message sender
sessionId
string
Session identifier for demo mode tracking

Example

const messages = await ctx.runQuery(api.messages.list, {
  roomId: "general"
});
messages.forEach(msg => {
  console.log(`${msg.userName}: ${msg.content}`);
});

Presence

list

Get all active presence entries for a room, filtering out stale entries. Location: convex/presence.ts:29
export const list = query({
  args: { roomId: v.string() },
  returns: v.array(presenceValidator),
  handler: async (ctx, args) => {
    const now = Date.now();
    const presenceList = await ctx.db
      .query("presence")
      .withIndex("by_room", (q) => q.eq("roomId", args.roomId))
      .collect();
    
    // Filter out stale presence entries
    return presenceList.filter((p) => now - p.lastSeen < PRESENCE_TIMEOUT);
  },
});

Arguments

roomId
string
required
The room identifier to fetch presence data from

Returns

presence
array
Array of active presence entries (within last 30 seconds)
_id
Id<'presence'>
Presence entry unique identifier
_creationTime
number
Timestamp when presence was created
roomId
string
Room identifier
userId
Id<'users'>
User ID (optional for demo mode)
sessionId
string
Session identifier for demo mode
data
object
Presence data object
cursor
{x: number, y: number}
Cursor position coordinates
position
{x: number, y: number}
Position coordinates (alias for cursor)
status
string
User status text
userName
string
User’s display name
userImage
string
URL to user’s avatar
color
string
Color code for cursor/avatar
name
string
Alternative name field
lastSeen
number
Timestamp of last update

Example

const activeUsers = await ctx.runQuery(api.presence.list, {
  roomId: "canvas-1"
});
activeUsers.forEach(p => {
  console.log(`${p.data.userName} at (${p.data.cursor?.x}, ${p.data.cursor?.y})`);
});

Notes

  • Automatically filters out entries older than 30 seconds (PRESENCE_TIMEOUT)
  • Returns empty array if no active presence

Files

getUrl

Get the download URL for a file stored in Convex storage. Location: convex/files.ts:48
export const getUrl = query({
  args: { storageId: v.id("_storage") },
  returns: v.union(v.string(), v.null()),
  handler: async (ctx, args) => {
    return await ctx.storage.getUrl(args.storageId);
  },
});

Arguments

storageId
Id<'_storage'>
required
The storage ID of the file

Returns

url
string | null
The URL to access the file, or null if file doesn’t exist

Example

const url = await ctx.runQuery(api.files.getUrl, {
  storageId: "kg2abc123..."
});
if (url) {
  window.open(url);
}

list

List files for the current user or session. Location: convex/files.ts:57
export const list = query({
  args: { sessionId: v.optional(v.string()) },
  returns: v.array(
    v.object({
      ...fileValidator.fields,
      url: v.union(v.string(), v.null()),
    }),
  ),
  handler: async (ctx, args) => {
    const userId = await getAuthUserId(ctx);
    
    let files;
    if (userId) {
      files = await ctx.db
        .query("files")
        .withIndex("by_user", (q) => q.eq("userId", userId))
        .collect();
    } else if (args.sessionId) {
      files = await ctx.db
        .query("files")
        .withIndex("by_session", (q) => q.eq("sessionId", args.sessionId))
        .collect();
    } else {
      return [];
    }
    
    return await Promise.all(
      files.map(async (file) => ({
        ...file,
        url: await ctx.storage.getUrl(file.storageId),
      })),
    );
  },
});

Arguments

sessionId
string
Session identifier for demo mode. Required if user is not authenticated.

Returns

files
array
Array of file objects with download URLs
_id
Id<'files'>
File unique identifier
_creationTime
number
Timestamp when file was uploaded
storageId
Id<'_storage'>
Reference to Convex storage
userId
Id<'users'>
ID of user who uploaded the file
sessionId
string
Session identifier for demo uploads
name
string
Original filename
type
string
MIME type of the file
size
number
File size in bytes
url
string | null
Download URL for the file

Example

// Authenticated user
const files = await ctx.runQuery(api.files.list, {});

// Demo mode
const files = await ctx.runQuery(api.files.list, {
  sessionId: "session_xyz"
});

files.forEach(file => {
  console.log(`${file.name} (${file.size} bytes): ${file.url}`);
});

Notes

  • For authenticated users: returns their files
  • For demo mode: returns files for the given sessionId
  • Returns empty array if neither userId nor sessionId is available

Build docs developers (and LLMs) love