QuickStart
Go from an empty project to a generated client, reviewed migration, and working CRUD code.
QuickStart
This page is the shortest complete path through comon_orm.
By the end you will have:
- a
schema.prismafile - a generated Dart client
- a reviewed migration for a shared database
- working CRUD code against the generated delegates
1. Write schema.prisma
Start with one schema that is rich enough to show the real workflow: enums, relations, defaults, timestamps, and an implicit many-to-many relation.
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "comon_orm"
output = "lib/generated/comon_orm_client.dart"
}
enum Role {
admin
member
}
enum PostStatus {
draft
published
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
role Role @default(member)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
status PostStatus @default(draft)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
tags Tag[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
posts Post[]
}2. Check and generate
Run schema validation first. Then generate the client.
dart run comon_orm check
dart run comon_orm generateTypical output shape:
Schema is valid.
Generated client written to lib/generated/comon_orm_client.dartcheck is the preferred command name. validate still exists as an alias, but the docs use check consistently.
3. Draft and review a migration
For shared databases, do not jump straight from generation to runtime.
For day-to-day local development, the shortest path is migrate dev.
dart run comon_orm migrate dev --name 20260318_initial_blogThis creates a migration artifact in prisma/migrations, applies it to your local database, and refreshes the generated client.
For reviewed rollouts to shared databases, keep creation and deployment separate.
dart run comon_orm migrate status
dart run comon_orm migrate deploymigrate dev creates a directory similar to:
prisma/migrations/
20260318_initial_blog/
migration.sql
warnings.txt
before.prisma
after.prisma
metadata.txtThen inspect the artifact:
migration.sqlis the human-reviewed DDLwarnings.txtcontains destructive or rebuild-related warningsbefore.prismaandafter.prismacapture the schema snapshots used for review and rollback supportmetadata.txtstores migration metadata used for status and deploy flows
Check status whenever you suspect drift or before deploying to another environment:
dart run comon_orm migrate statusDeploy reviewed local migrations to shared environments with:
dart run comon_orm migrate deployImportant
Use migrate dev for local creation and application of a new migration. Use migrate deploy to apply already-reviewed local migrations to shared environments. Use db push only when you explicitly do not want migration history.
If you need the full command reference, continue with CLI commands after this page.
4. Open the generated client
With PostgreSQL, the normal runtime path is the generated opener:
import 'lib/generated/comon_orm_client.dart';
Future<void> main() async {
final db = await GeneratedComonOrmClientPostgresql.open();
try {
final user = await db.user.create(
data: const UserCreateInput(
email: 'alice@example.com',
name: 'Alice',
posts: PostCreateNestedManyWithoutAuthorInput(
create: <PostCreateWithoutAuthorInput>[
PostCreateWithoutAuthorInput(
title: 'QuickStart post',
content: 'Created from the generated client',
status: PostStatus.published,
),
],
),
),
include: const UserInclude(posts: true),
);
final publishedPosts = await db.post.findMany(
where: const PostWhereInput(
status: EnumFilter<PostStatus>(equals: PostStatus.published),
),
include: const PostInclude(
author: true,
tags: true,
),
);
print(user.email);
print(publishedPosts.length);
} finally {
await db.close();
}
}5. Flutter local SQLite variant
If the app owns a device-local SQLite file, the shape is similar but the rollout strategy changes.
Use a Flutter helper in the generator block:
generator client {
provider = "comon_orm"
output = "lib/generated/comon_orm_client.dart"
sqliteHelper = "flutter"
}Then upgrade local SQLite first and open the runtime second:
await upgradeSqliteFlutterDatabase(
databasePath: 'app.db',
migrator: migrator,
);
final db = await GeneratedComonOrmClientFlutterSqlite.open(
databasePath: 'app.db',
);That split is the core rule for Flutter local data:
- app-side upgrade first
- normal runtime open second
Operational rule
Use reviewed CLI migrations for shared databases. Use explicit app-side upgrades for device-local Flutter SQLite files with important data.