一键导入
function-creator
// Create Convex queries, mutations, and actions with proper validation, authentication, and error handling. Use when implementing new API endpoints.
// Create Convex queries, mutations, and actions with proper validation, authentication, and error handling. Use when implementing new API endpoints.
Integrate and maintain Robelest Convex Auth in apps by always checking upstream before implementation. Use when adding auth setup, updating auth wiring, migrating between upstream patterns, or troubleshooting @robelest/convex-auth behavior across projects.
Initialize a new Convex project from scratch or add Convex to an existing app. Use when starting a new project with Convex, scaffolding a Convex app, or integrating Convex into an existing frontend.
Set up Convex authentication with proper user management, identity mapping, and access control patterns. Use when implementing auth flows, setting up OAuth providers, or adding role-based access control.
Full-stack Convex development guidelines covering React, Vite, TypeScript, mutations, auth, design system, and documentation practices. Use when building features, writing Convex functions, or making code changes in this project.
Critical Git safety rules to prevent destructive operations. Use whenever performing git operations, reverting changes, or managing commits. Prevents accidental loss of work.
Reflection-first problem solving methodology for Convex development. Use before implementing any solution to ensure proper root cause analysis, 98% code confidence, and minimal change scope.
| name | function-creator |
| description | Create Convex queries, mutations, and actions with proper validation, authentication, and error handling. Use when implementing new API endpoints. |
Generate secure, type-safe Convex functions following all best practices.
import { query } from "./_generated/server";
import { v } from "convex/values";
export const getTask = query({
args: { taskId: v.id("tasks") },
returns: v.union(v.object({
_id: v.id("tasks"),
text: v.string(),
completed: v.boolean(),
}), v.null()),
handler: async (ctx, args) => {
return await ctx.db.get(args.taskId);
},
});
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const createTask = mutation({
args: {
text: v.string(),
priority: v.optional(v.union(
v.literal("low"),
v.literal("medium"),
v.literal("high")
)),
},
returns: v.id("tasks"),
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Not authenticated");
return await ctx.db.insert("tasks", {
text: args.text,
priority: args.priority ?? "medium",
completed: false,
createdAt: Date.now(),
});
},
});
ctx.runMutation"use node" directive when needing Node.js APIs"use node";
import { action } from "./_generated/server";
import { api } from "./_generated/api";
import { v } from "convex/values";
import OpenAI from "openai";
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
export const generateTaskSuggestion = action({
args: { prompt: v.string() },
returns: v.string(),
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Not authenticated");
const completion = await openai.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: args.prompt }],
});
const suggestion = completion.choices[0].message.content;
await ctx.runMutation(api.tasks.createTask, { text: suggestion });
return suggestion;
},
});
Note: Keep queries and mutations in files without "use node". Actions that need Node.js go in separate files with "use node".
Always define args with validators.
Always define returns.
Always verify auth in public functions:
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Not authenticated");
Always verify ownership/permissions:
const task = await ctx.db.get(args.taskId);
if (!task) throw new Error("Task not found");
if (task.userId !== user._id) throw new Error("Unauthorized");
For backend-only functions (called by scheduler, other functions):
import { internalMutation } from "./_generated/server";
export const processExpiredTasks = internalMutation({
args: {},
handler: async (ctx) => {
const now = Date.now();
const expired = await ctx.db
.query("tasks")
.withIndex("by_due_date", q => q.lt("dueDate", now))
.collect();
for (const task of expired) {
await ctx.db.patch(task._id, { status: "expired" });
}
},
});
args defined with validatorsreturns defined with validatorctx.auth.getUserIdentity()).filter() on queries)internal.* not api.*"use node" at top of file"use node": Only actions (no queries/mutations)