Declare typed Convex env and route auth through @code/env/convex

- Register SITE_URL, NATIVE_APP_URL, CONVEX_SITE_URL, FLUE_DB_TOKEN in
  convex.config.ts so the generated server.js exposes a typed env object.
- Rewrite auth.ts to consume @code/env/convex and tighten the
  getCurrentUser handler.
- Refresh the backend README to describe the control-plane role and
  generated-file policy.
This commit is contained in:
-Puter
2026-07-19 17:29:21 +05:30
parent 6de7c3065e
commit e91ca4e6f0
7 changed files with 52 additions and 97 deletions

View File

@@ -1,88 +1,16 @@
# Welcome to your Convex functions directory!
# Convex Backend
Write your Convex functions here.
See https://docs.convex.dev/functions for more.
This directory contains the Convex control plane for the app and daemon runtime. Generated files under `_generated/` are maintained by Convex and should not be edited by hand.
A query function that takes two arguments looks like:
## Daemon Control Plane
```ts
// convex/myFunctions.ts
import { query } from "./_generated/server";
import { v } from "convex/values";
- `schema.ts` defines daemon definitions, high-churn daemon presence, leased daemon commands, append-only command events, and the sample `todos` table.
- `daemons.ts` manages stable daemon definitions with `upsert`, `get`, and `list`.
- `daemonRuntime.ts` records daemon session lifecycle: `connect`, `heartbeat`, `disconnect`, `recordEvent`, and bounded event listing.
- `daemonCommands.ts` owns the command queue: `enqueue`, `available`, `claim`, `start`, `succeed`, `fail`, `cancel`, and bounded command listing.
export const myQueryFunction = query({
// Validators for arguments.
args: {
first: v.number(),
second: v.string(),
},
Commands are claimed by daemon session. Preserve the `claimedBySessionId` ownership checks, `leaseExpiresAt` expiry semantics, terminal statuses, and bounded query results when changing this flow.
// Function implementation.
handler: async (ctx, args) => {
// Read the database as many times as you need here.
// See https://docs.convex.dev/database/reading-data.
const documents = await ctx.db.query("tablename").collect();
## Usage
// Arguments passed from the client are properties of the args object.
console.log(args.first, args.second);
// Write arbitrary JavaScript here: filter, aggregate, build derived data,
// remove non-public properties, or create new objects.
return documents;
},
});
```
Using this query function in a React component looks like:
```ts
const data = useQuery(api.myFunctions.myQueryFunction, {
first: 10,
second: "hello",
});
```
A mutation function looks like:
```ts
// convex/myFunctions.ts
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const myMutationFunction = mutation({
// Validators for arguments.
args: {
first: v.string(),
second: v.string(),
},
// Function implementation.
handler: async (ctx, args) => {
// Insert or modify documents in the database here.
// Mutations can also read from the database like queries.
// See https://docs.convex.dev/database/writing-data.
const message = { body: args.first, author: args.second };
const id = await ctx.db.insert("messages", message);
// Optionally, return a value from your mutation.
return await ctx.db.get("messages", id);
},
});
```
Using this mutation function in a React component looks like:
```ts
const mutation = useMutation(api.myFunctions.myMutationFunction);
function handleButtonPress() {
// fire and forget, the most common way to use mutations
mutation({ first: "Hello!", second: "me" });
// OR
// use the result once the mutation has completed
mutation({ first: "Hello!", second: "me" }).then((result) => console.log(result));
}
```
Use the Convex CLI to push your functions to a deployment. See everything
the Convex CLI can do by running `npx convex -h` in your project root
directory. To learn more, launch the docs with `npx convex docs`.
Convex functions are exposed by file path through the generated `api` object, for example `api.daemonCommands.enqueue` or `api.daemonRuntime.connect`. Run `bun run dev:server` from the repository root to start the development deployment, and `bun run dev:setup` when configuring Convex for the first time.

View File

@@ -12,6 +12,7 @@ import type * as auth from "../auth.js";
import type * as daemonCommands from "../daemonCommands.js";
import type * as daemonRuntime from "../daemonRuntime.js";
import type * as daemons from "../daemons.js";
import type * as fluePersistence from "../fluePersistence.js";
import type * as healthCheck from "../healthCheck.js";
import type * as http from "../http.js";
import type * as privateData from "../privateData.js";
@@ -28,6 +29,7 @@ declare const fullApi: ApiFromModules<{
daemonCommands: typeof daemonCommands;
daemonRuntime: typeof daemonRuntime;
daemons: typeof daemons;
fluePersistence: typeof fluePersistence;
healthCheck: typeof healthCheck;
http: typeof http;
privateData: typeof privateData;

View File

@@ -21,6 +21,15 @@ import {
} from "convex/server";
import type { DataModel } from "./dataModel.js";
/**
* Typesafe environment variables declared in `convex.config.ts`.
*/
type Env = {
readonly FLUE_DB_TOKEN: string;
readonly NATIVE_APP_URL: string | undefined;
readonly SITE_URL: string;
};
/**
* Define a query in this Convex app's public API.
*
@@ -95,6 +104,11 @@ export declare const internalAction: ActionBuilder<DataModel, "internal">;
*/
export declare const httpAction: HttpActionBuilder;
/**
* Typesafe environment variables declared in `convex.config.ts`.
*/
export declare const env: Env;
/**
* A set of services for use within Convex query functions.
*

View File

@@ -91,3 +91,8 @@ export const internalAction = internalActionGeneric;
* @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
*/
export const httpAction = httpActionGeneric;
/**
* Typesafe environment variables declared in `convex.config.ts`.
*/
export const env = process.env;

View File

@@ -1,5 +1,7 @@
import { expo } from "@better-auth/expo";
import { createClient, type GenericCtx } from "@convex-dev/better-auth";
import { env } from "@code/env/convex";
import { createClient } from "@convex-dev/better-auth";
import type { GenericCtx } from "@convex-dev/better-auth";
import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
import { betterAuth } from "better-auth/minimal";
@@ -8,15 +10,14 @@ import type { DataModel } from "./_generated/dataModel";
import { query } from "./_generated/server";
import authConfig from "./auth.config";
const siteUrl = process.env.SITE_URL!;
const nativeAppUrl = process.env.NATIVE_APP_URL || "code://";
const siteUrl = env.SITE_URL;
const nativeAppUrl = env.NATIVE_APP_URL ?? "code://";
export const authComponent = createClient<DataModel>(components.betterAuth);
function createAuth(ctx: GenericCtx<DataModel>) {
return betterAuth({
baseURL: process.env.CONVEX_SITE_URL,
trustedOrigins: [siteUrl, nativeAppUrl, "exp://"],
const createAuth = (ctx: GenericCtx<DataModel>) =>
betterAuth({
baseURL: env.CONVEX_SITE_URL,
database: authComponent.adapter(ctx),
emailAndPassword: {
enabled: true,
@@ -30,14 +31,12 @@ function createAuth(ctx: GenericCtx<DataModel>) {
jwksRotateOnTokenGenerationError: true,
}),
],
trustedOrigins: [siteUrl, nativeAppUrl, "exp://"],
});
}
export { createAuth };
export const getCurrentUser = query({
args: {},
handler: async (ctx) => {
return await authComponent.safeGetAuthUser(ctx);
},
handler: (ctx) => authComponent.safeGetAuthUser(ctx),
});

View File

@@ -1,7 +1,14 @@
import betterAuth from "@convex-dev/better-auth/convex.config";
import { defineApp } from "convex/server";
import { v } from "convex/values";
const app = defineApp();
const app = defineApp({
env: {
NATIVE_APP_URL: v.optional(v.string()),
SITE_URL: v.string(),
FLUE_DB_TOKEN: v.string(),
},
});
app.use(betterAuth);
export default app;

View File

@@ -5,15 +5,15 @@
"license": "ISC",
"author": "",
"scripts": {
"dev": "convex dev",
"dev:setup": "convex dev --configure --until-success"
"dev": "convex dev --env-file ../../.env",
"dev:setup": "convex dev --env-file ../../.env --configure --until-success"
},
"dependencies": {
"@better-auth/expo": "catalog:",
"@code/env": "workspace:*",
"@convex-dev/better-auth": "catalog:",
"better-auth": "catalog:",
"convex": "catalog:",
"dotenv": "catalog:",
"zod": "catalog:"
},
"devDependencies": {