Generators
Generators transform your opensaas.config.ts into Prisma schemas and TypeScript types.
Overview
The generator system reads your declarative config and creates:
- Prisma Schema (
prisma/schema.prisma) - TypeScript Types (
.opensaas/types.ts) - Context Factory (
.opensaas/context.ts)
Running the Generator
pnpm opensaas generate
Or in a specific example:
cd examples/blog
pnpm generate
What Gets Generated
1. Prisma Schema
From your config:
Post: list({
fields: {
title: text({ validation: { isRequired: true } }),
author: relationship({ ref: 'User.posts' }),
},
})
The generator creates:
model Post {
id String @id @default(cuid())
title String
authorId String
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
2. TypeScript Types
Type-safe types for all your lists:
export type Lists = {
Post: {
fields: {
title: string
author: User
}
}
// ... more lists
}
3. Context Factory
Auto-generated context creation function:
import { getContext } from '@/.opensaas/context'
const context = await getContext({ userId: '123' })
Generator Architecture
Generators delegate to field builder methods rather than using switch statements. Each field type provides its own generation logic:
text({
getPrismaType: (fieldName) => {
return { type: 'String', modifiers: '?' }
},
getTypeScriptType: () => {
return { type: 'string', optional: true }
},
})
This allows field types to be fully self-contained and extensible.
Custom Prisma Client Constructor
To use custom database drivers (e.g., Neon, Turso, PlanetScale), provide a prismaClientConstructor:
export default config({
db: {
provider: 'postgresql',
url: process.env.DATABASE_URL,
prismaClientConstructor: (PrismaClient) => {
const adapter = new PrismaNeon({
connectionString: process.env.DATABASE_URL,
})
return new PrismaClient({ adapter })
},
},
// ... rest of config
})
Generator Limitations
Current generators are basic:
- ❌ No migration support (use
prisma db push) - ❌ No introspection support
- ❌ Limited Prisma features (no raw queries, advanced transactions)
Best Practices
1. Regenerate After Config Changes
Always run the generator after modifying your config:
pnpm generate
2. Commit Generated Files
Commit the generated files to version control for consistency:
git add prisma/schema.prisma
git add .opensaas/
git commit -m "Regenerate schema"
3. Use Type-Safe Operations
Use the generated types for type safety:
import type { Lists } from '@/.opensaas/types'
const post: Lists['Post'] = await context.db.post.findUnique({
where: { id: '123' },
})
Next Steps
- Config System - Learn about config options
- Field Types - Available field types