A Prisma generator that creates Effect Schema types from Prisma schema definitions with exact type safety and intelligent UUID detection.
- ✅ Type-Safe Generation: Zero type coercion, complete type safety
- ✅ Intelligent UUID Detection: Via
@db.Uuid,nativeType, or field name patterns - ✅ Enum Support: Effect Schema enums with
@mapannotation support - ✅ Deterministic Output: Alphabetically sorted for consistent results
- ✅ Complete Type Mappings: All Prisma types mapped to Effect Schema equivalents
npm install prisma-effect-kysely
# or
pnpm add prisma-effect-kysely
# or
yarn add prisma-effect-kyselygenerator effect_schemas {
provider = "prisma-effect-kysely"
output = "./generated/effect"
}npx prisma generateGenerates three files in the configured output directory:
Effect Schema enums from Prisma enums with exact literal types:
export const UserRoleSchema = Schema.Literal('admin', 'user', 'guest');Effect Schema structs from Prisma models with Kysely integration:
// Internal (not exported) - Kysely table interface
interface UserTable {
id: ColumnType<string, never, never>;
email: string;
createdAt: ColumnType<Date, Date | undefined, Date | undefined>;
}
// Internal (not exported) - Base schema
const _User = Schema.Struct({
id: columnType(Schema.UUID, Schema.Never, Schema.Never),
email: Schema.String,
createdAt: generated(Schema.DateFromSelf),
});
// Internal (not exported) - Branded ID
const UserIdSchema = Schema.UUID.pipe(Schema.brand("UserId"));
// EXPORTED - Operational schemas with branded Id
export const User = getSchemas(_User, UserIdSchema);
// EXPORTED - Kysely DB interface
export interface DB {
User: UserTable;
}Re-exports all generated types for easy importing
Use type utilities from prisma-effect-kysely to extract types:
import { Selectable, Insertable, Updateable, Id } from "prisma-effect-kysely";
import { User, DB } from "./generated";
// Extract types using utilities (Kysely-native pattern)
type UserSelect = Selectable<typeof User>;
type UserInsert = Insertable<typeof User>;
type UserUpdate = Updateable<typeof User>;
type UserId = Id<typeof User>;
// Use with Kysely
import { Kysely } from 'kysely';
const db = new Kysely<DB>({ ... });
// Type-safe queries
const user = await db.selectFrom('User').selectAll().executeTakeFirst();Naming Convention: All exported schemas use PascalCase, regardless of the Prisma model naming convention:
- Model
User→export const User - Model
session_preference→export const SessionPreference
| Prisma Type | Effect Schema Type | Notes |
|---|---|---|
| String | Schema.String |
Schema.UUID for id fields |
| Int / Float | Schema.Number |
With Schema.int() for integers |
| BigInt | Schema.BigInt |
Exact bigint type |
| Decimal | Schema.String |
String for precision |
| Boolean | Schema.Boolean |
- |
| DateTime | Schema.DateFromSelf |
Native Date for Kysely |
| Json | Schema.Unknown |
Safe unknown type |
| Bytes | Schema.Uint8Array |
- |
| Enum | Enum Schema | With Schema.Literal values |
The generator intelligently detects UUID fields through multiple strategies (in order):
- Native Type:
@db.Uuidattribute (most reliable) - Documentation:
@db.Uuidin field comments - Default Value:
dbgenerated("gen_random_uuid()")or similar - Field Name Patterns:
id,*_id,*_uuid,uuid
Example:
model User {
id String @id @db.Uuid @default(dbgenerated("gen_random_uuid()"))
userId String @db.Uuid // Detected via native type
productId String // Detected via field name pattern
}# Install dependencies
pnpm install
# Run tests
pnpm test
# Run tests in watch mode
pnpm run test:watch
# Run tests with coverage
pnpm run test:coverage
# Type check
pnpm run typecheck
# Build
pnpm run buildThis project uses Changesets for automated versioning and publishing:
-
Add a changeset for your changes:
pnpm changeset
Follow the prompts to describe your changes (patch/minor/major).
-
Commit the changeset:
git add .changeset/ git commit -m "docs: add changeset for [feature/fix]" git push -
Automated Release PR: The CI will automatically:
- Create or update a "Version Packages" PR
- Update
package.jsonversion - Update
CHANGELOG.md
-
Publish: When you merge the "Version Packages" PR:
- CI automatically publishes to npm using Bun
- Creates a git tag (e.g.,
v1.15.0) - Creates a GitHub release with auto-generated notes
# Build and run all checks
pnpm run prepublishOnly
# Publish with Bun (recommended)
bun publish --access publicThis repo uses Changesets to automate versioning, changelog updates, npm publishing, git tags, and GitHub Releases.
Add a changeset for any user-facing change:
pnpm changesetCommit the generated file in .changeset/.
- When changesets land on
main, CI opens/updates a Version Packages PR. - When the Version Packages PR is merged, CI:
- updates
package.json+CHANGELOG.md - publishes to npm (with provenance)
- creates/pushes
vX.Y.Ztag - creates a GitHub Release
- updates
NPM_TOKEN: npm access token with permission to publishprisma-effect-kysely
This generator uses EXACT DMMF types from Prisma and implements zero type coercion:
- Uses
FieldDefaulttype matching Prisma's exact structure - Type-safe validation with structural typing
- No
asassertions or unsafe casts - Complete TypeScript strict mode compliance
- Alphabetically sorted fields and models for consistency
- Branded types for UUIDs via
Schema.UUID - Exact type inference - no widening to
anyorunknown - Auto-generated headers with timestamps and edit warnings
Use @customType annotations to override Effect Schema types for Prisma-supported fields:
model User {
/// @customType(Schema.String.pipe(Schema.email()))
email String @unique
/// @customType(Schema.Number.pipe(Schema.positive()))
age Int
/// @customType(Schema.String.pipe(Schema.brand('UserId')))
userId String
}Supported for: All Prisma scalar types (String, Int, Float, Boolean, DateTime, BigInt, Decimal, Json, Bytes)
Use cases:
- Email/URL validation
- Number constraints (positive, range, etc.)
- Custom branded types
- Refined string patterns
Examples:
// Generated from Prisma schema with @customType annotations
export const _User = Schema.Struct({
email: Schema.String.pipe(Schema.email()),
age: Schema.Number.pipe(Schema.positive()),
userId: Schema.String.pipe(Schema.brand('UserId')),
});If you're developing the generator locally, make sure to build it first:
npm run buildThen reference it in your schema.prisma:
generator effect_schemas {
provider = "node ./path/to/dist/generator.js"
output = "./generated/effect"
}Check the generator output in console:
[Effect Generator] Starting generation...
[Effect Generator] Processing 15 models, 3 enums
[Effect Generator] ✓ Generated to ../../libs/types/storage/src/lib/effect
Add explicit @db.Uuid attribute:
userId String @db.UuidMIT