The @packages/database package provides a fully-typed Convex database layer with schema definitions, organized functions (public/authenticated/private), and Better Auth integration.
Installation
npm install @packages/database
Overview
This package centralizes all database operations for Answer Overflow, including:
- Schema definitions using Effect Schema and Convex
- Function organization (public, authenticated, private)
- Better Auth integration for authentication
- Discord data models (servers, channels, messages, users)
- Analytics and tracking with PostHog
Schema Structure
The database schema is defined in convex/schema.ts using Effect Schema:
import { defineSchema, defineTable } from "@packages/confect/server";
import { Schema } from "effect";
const ServerSchema = Schema.Struct({
discordId: Schema.BigIntFromSelf,
name: Schema.String,
icon: Schema.optional(Schema.String),
banner: Schema.optional(Schema.String),
description: Schema.optional(Schema.String),
approximateMemberCount: Schema.Number,
});
Core Tables
Discord servers indexed by Answer OverflowDiscord server snowflake ID
Server-specific preferences and settingsAssociated Discord server ID
Subscription plan: FREE, STARTER, ADVANCED, PRO, ENTERPRISE, OPEN_SOURCE
Stripe customer ID for billing
Custom domain for the server’s docs
Discord channels being indexedDiscord channel snowflake ID
Discord user accountsDiscord user snowflake ID
User settings per serverPermission bitfield from Discord
canPubliclyDisplayMessages
Whether messages can be displayed publicly
Whether to disable message indexing
Function Organization
Convex functions are organized into three categories:
Public Functions
Located in convex/public/ - accessible without authentication:
// convex/public/messages.ts
import { query } from "../_generated/server";
export const getPublicMessages = query({
handler: async (ctx, args) => {
// Public message retrieval logic
}
});
Available public functions:
messages.ts - Public message queries
channels.ts - Channel data
discord_accounts.ts - Public user profiles
search.ts - Search functionality
Authenticated Functions
Located in convex/authenticated/ - requires user authentication:
// convex/authenticated/dashboard.ts
import { authenticatedMutation } from "../auth";
export const updateServerSettings = authenticatedMutation({
handler: async (ctx, args) => {
const user = await ctx.auth.getUserIdentity();
// Update logic
}
});
Available authenticated functions:
dashboard.ts - Dashboard queries
dashboard_queries.ts - Dashboard data
dashboard_mutations.ts - Dashboard updates
onboarding.ts - Onboarding flow
stripe.ts - Stripe operations
github.ts - GitHub integration
Private Functions
Located in convex/private/ - internal functions only:
// convex/private/servers.ts
import { internalMutation } from "../_generated/server";
export const upsertServer = internalMutation({
handler: async (ctx, args) => {
// Server upsert logic
}
});
Better Auth Integration
The package integrates Better Auth for authentication:
import { betterAuth } from "better-auth";
import { convexAdapter } from "@convex-dev/better-auth";
export const auth = betterAuth({
database: convexAdapter(/* ... */),
// Auth configuration
});
Auth Schema
Generated schema in convex/betterAuth/generatedSchema.ts includes:
- User tables
- Session management
- OAuth providers
- Account linking
Client Usage
Import and use the database client:
import { Database } from "@packages/database/database";
import { Effect } from "effect";
// Example: Query servers
const getServer = Effect.gen(function* () {
const database = yield* Database;
const server = yield* database.private.servers.getServerByDiscordId(
{ discordId: BigInt("123456789") },
{ subscribe: false }
);
return server;
});
Testing
The package includes comprehensive testing utilities:
import { describe, expect, it } from "@effect/vitest";
import { Effect } from "effect";
import { Database } from "@packages/database/database";
import { DatabaseTestLayer } from "@packages/database/database-test";
describe("Database tests", () => {
it.scoped("should query data", () =>
Effect.gen(function* () {
const database = yield* Database;
const result = yield* database.private.servers.upsertServer({
discordId: BigInt(Date.now()),
name: "Test Server",
approximateMemberCount: 100,
});
expect(result).toBeDefined();
}).pipe(Effect.provide(DatabaseTestLayer))
);
});
Exports
Convex function exports (compiled JavaScript)
Shared types and utilities
Scripts
# Deploy to Convex
bun run deploy
# Generate code from schema
bun run codegen
# Generate Better Auth schema
bun run generate:auth-schema
# Run tests
bun run test
# Development mode
bun run dev