Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@formbricks/database
The database package for the Formbricks monorepo, providing centralized database schema management, migration handling, and type definitions for the entire platform.
Overview
This package serves as the central database layer for Formbricks, containing:
- Prisma Schema: Complete database schema definition with PostgreSQL support
- Migration System: Custom migration management for both schema and data migrations
- Type Definitions: Zod schemas and TypeScript types for database models
- Database Client: Configured Prisma client with extensions and generators
- Migration Scripts: Automated tools for creating and applying migrations
Package Structure
packages/database/
├── src/
│ ├── client.ts # Prisma client configuration
│ ├── index.ts # Package exports
│ └── scripts/ # Migration management scripts
│ ├── apply-migrations.ts
│ ├── create-migration.ts
│ ├── generate-data-migration.ts
│ ├── migration-runner.ts
│ └── create-saml-database.ts
├── migration/ # Custom migrations directory
│ ├── [timestamp_name]/ # Schema migration folder
│ │ └── migration.sql # Schema migration file
│ └── [timestamp_name]/ # Data migration folder
│ └── migration.ts # Data migration file
├── migrations/ # Prisma internal migrations
├── types/ # Custom TypeScript types
├── zod/ # Zod schema definitions
├── schema.prisma # Main Prisma schema file
└── package.json
Migration System
Key Features
- Custom Migrations Directory: Schema and data migrations are managed in the
packages/database/migrationdirectory - Separation of Concerns: Each migration is classified as either:
- Schema Migration: Contains a
migration.sqlfile - Data Migration: Contains a
migration.tsfile
- Schema Migration: Contains a
- Single Type per Subdirectory: A migration subdirectory can only contain one file type—either
migration.sqlormigration.ts - Custom Naming Convention: Subdirectories follow the format
timestamp_name_of_the_migration(e.g.,20241214112456_add_users_table) - Order of Execution: Migrations are executed sequentially based on their timestamps, enabling precise control over the execution sequence
Database Tracking
- Schema Migrations: Continue to be tracked by Prisma in the
_prisma_migrationstable - Data Migrations: Are tracked in the new
DataMigrationtable to avoid reapplying already executed migrations
Directory Structure Example
packages/database/migration/
├── 20241214112456_xm_user_identification/
│ └── migration.sql
├── 20241214113000_xm_user_identification/
│ └── migration.ts
└── 20241215120000_add_new_feature/
└── migration.sql
Each subdirectory under packages/database/migration represents a single migration and must:
- Have a 14-digit UTC timestamp followed by an underscore and the migration name (similar to Prisma)
- Contain only one file, either
migration.sql(for schema migrations) ormigration.ts(for data migrations)
Scripts and Commands
Root Level Commands
Run these commands from the root directory of the Formbricks monorepo:
pnpm fb-migrate-dev: Create and apply schema migrations- Prompts for migration name
- Generates new
migration.sqlin the custom directory - Copies migration to Prisma's internal directory
- Applies all pending migrations to the database
Package Level Commands
Run these commands from the packages/database directory:
pnpm generate-data-migration: Create data migrations- Prompts for data migration name
- Creates new subdirectory with appropriate timestamp
- Generates
migration.tsfile with pre-configured ID and name - Note: Only use Prisma raw queries in data migrations for better performance and to avoid type errors
Available Scripts
{
"build": "pnpm generate && vite build",
"create-migration": "Create new schema migration",
"db:migrate:deploy": "Apply migrations in production",
"db:migrate:dev": "Apply migrations in development",
"db:push": "prisma db push --accept-data-loss",
"db:setup": "pnpm db:migrate:dev && pnpm db:create-saml-database:dev",
"dev": "vite build --watch",
"generate": "prisma generate",
"generate-data-migration": "Create new data migration"
}
Migration Workflow
Adding a Schema Migration
- Modify your Prisma schema in
schema.prisma - Run
pnpm fb-migrate-devfrom the root of the monorepo - Follow the prompts to name your migration
- The script automatically:
- Generates the new
migration.sqlfile in the custom directory - Copies the file to Prisma's internal directory
- Applies the migration to the database
- Generates the new
Adding a Data Migration
- Navigate to the
packages/databasedirectory - Run
pnpm generate-data-migration - Follow the prompts to name your migration
- Implement the required data changes in the generated
migration.tsfile - Use only Prisma raw queries for optimal performance
Example Data Migration Structure
import { createId } from "@paralleldrive/cuid2";
import { Prisma } from "@prisma/client";
import { logger } from "@formbricks/logger";
import type { MigrationScript } from "../../src/scripts/migration-runner";
export const myDataMigration: MigrationScript = {
type: "data",
id: "unique_migration_id",
name: "20241214113000_my_data_migration",
run: async ({ tx }) => {
// Use raw SQL queries for data transformations
const result = await tx.$queryRaw`
UPDATE "MyTable" SET "newField" = 'defaultValue' WHERE "newField" IS NULL
`;
logger.info(`Updated ${result} records`);
},
};
Database Schema
The package uses PostgreSQL with the following key features:
- Extensions: pgvector for vector operations
- Generators:
- Prisma Client with PostgreSQL extensions
- JSON types generator for enhanced type safety
- Models: Comprehensive schema covering users, organizations, surveys, responses, webhooks, and more
Key Models
- User: User accounts with authentication and profile data
- Organization: Multi-tenant organization structure
- Project: Project-level configuration and settings
- Survey: Survey definitions with advanced targeting and styling
- Response: Survey response data with metadata
- Contact: Contact management and attributes
- Webhook: Event-driven integrations
- ApiKey: API authentication and access control
Type Definitions
Zod Schemas
Located in the zod/ directory, providing runtime validation for:
- API keys
- Contacts and contact attributes
- Organizations and teams
- Surveys and responses
- Webhooks and integrations
- User management
TypeScript Types
Custom types in the types/ directory for:
- Error handling
- Survey follow-up logic
- Complex data structures
Development
Prerequisites
- PostgreSQL database
- Redis (for caching)
- Node.js and pnpm
Setup
- Ensure database is running:
pnpm db:up(from root) - Install dependencies:
pnpm install - Generate Prisma client:
pnpm generate - Apply migrations:
pnpm db:setup
Building
# Development build with watch
pnpm dev
# Production build
pnpm build
Key Benefits
- Unified Management: Schema and data migrations are managed together in a single directory
- Controlled Execution: Timestamp-based sorting ensures migrations run in the desired sequence
- Automation: Simplifies the process of creating, copying, and applying migrations with custom scripts
- Tracking: Separate tracking for schema and data migrations prevents duplicate executions
- Type Safety: Comprehensive Zod schemas and TypeScript types for all database operations
- Performance: Optimized queries and proper indexing for production workloads
Contributing
When making changes to the database schema:
- Always create migrations for schema changes
- Use data migrations for data transformations
- Follow the naming conventions for migration directories
- Test migrations thoroughly in development before applying to production
- Document any breaking changes or special considerations
For more information about the Formbricks project structure, see the main repository README.