@abcx3/prisma-generator-dart
v3.0.1
Published
Automatically generate Dart classes and stores from a Prisma schema
Maintainers
Readme
@abcx3/prisma-generator-dart
Generate Dart model classes and fully-typed reactive Stores for every Prisma model. In addition to fromJson/toJson for models, this generator emits rich Store types with streaming, caching, include helpers for relations, endpoint metadata and Prisma-style filters.
Features
- Models
fromJsonconstructors (incl. nested objects)toJson(omits null-valued properties since 1.2.0)==andhashCodeby property valuescopyWithandcopyWithInstance(since 1.4.0, updated in 3.0.0)_countsupport for list-type fields (e.g.posts→$postsCount)- NEW in 3.0:
$assignedFieldstracking for true partial updates
- Stores
- Per-model
<Model>Storebuilt onModelStreamStorefor reactive updates getAll$,getBy<Field>$,getManyBy<Field>$stream helpersModelFilter,LogicalFilterGroup,PropertyFilter,FilterOperatorfor Prisma-like server-side filtering- Include helpers to lazily load relations (
<Model>Include) - Deduplication and in-memory caching
- Recursive upserts for relation graphs
- NEW in 3.0: In-place mutation for updates (
update()) vs replacement (replace())
- Per-model
- Endpoints
- Each store embeds a
<Model>Endpointsenum with route + method per supported call - Optional global endpoint generation by scanning a NestJS backend (see GenerateEndpoints)
- Each store embeds a
Breaking Changes in v3.0.0
copyWith and Value Wrapper
To support explicitly setting nullable fields to null vs ignoring them, copyWith now uses a Value wrapper.
Old Code:
user.copyWith(name: "Alice", age: null); // Error: age cannot be set to null if undefined is same as nullNew Code:
user.copyWith(
name: Value("Alice"), // Update value
age: Value(null), // Clear value
// email: ... // Omitted = no change
);update() vs replace()
store.update(item)now mutates the existing object instance in place. This preserves references held by Flutter widgets.store.replace(item)replaces the object instance in the store with the new one (old behavior).
Installation
Add the generator to the workspace that contains your Prisma schema (often the backend repo):
bash npm i -D @abcx3/prisma-generator-dart
Usage
Open your schema.prisma and add a generator block that targets your Flutter/Dart app output folder:
// schema.prisma
generator dart {
provider = "node ./node_modules/@abcx3/prisma-generator-dart/index.js"
output = "/absolute/path/to/your/flutter/app/lib/gen_models"
// Optional settings
FormatWithDart = true
MakeAllPropsOptional = true
UpdateStoresDefaultRecursiveDepth = 4
// GenerateEndpoints = true // also generate a single routes file by scanning backend
// BackendPath = "../abcx3-backend" // backend root to scan for NestJS controllers
// EndpointsOutputPath = "gen_backend_routes.dart"
// outputSetupForDevtools = true // also emit setup_stores_devtool.dart
}Configuration reference
| Name | Type | Default | Description |
| ----------------------------- | -------- | -------------------- | ----------- |
| provider | string | — | Must be node ./node_modules/@abcx3/prisma-generator-dart/index.js |
| output | string | — | Absolute path inside your Flutter app (e.g. lib/gen_models). The folder is created if missing. |
| dryRun | boolean | false | Write nothing, print to console instead. |
| FormatWithDart | boolean | true | Runs dart format on the generated output. |
| MakeAllPropsOptional | boolean | true | Emit model fields as nullable by default. |
| UpdateStoresDefaultRecursiveDepth | number | 4 | Default recursion depth for relation upserts inside stores. |
| GenerateEndpoints | boolean | false | Also generate a single gen_backend_routes.dart enum by scanning your backend. |
| BackendPath | string | ../abcx3-backend | Root of your NestJS backend for route scanning (when GenerateEndpoints is true). |
| EndpointsOutputPath | string | gen_backend_routes.dart | Output file for the routes enum (inside output). |
| outputSetupForDevtools | boolean | false | Also emit a setup_stores_devtool.dart helper. Requires abcx3_store_devtool. |
DevTools setup file
When outputSetupForDevtools is true, the generator writes a setup_stores_devtool.dart file next to the generated libraries. Import and call setupAbcx3StoresDevTool() from your Flutter main() in debug builds to stream all store updates to the DevTools UI. Using the stores requires you to install the abcx3_store_devtool package in the hosting Flutter app.
Using the generated Stores
Import the stores library into your Flutter app:
dart import 'package:your_app/gen_models/abcx3_stores_library.dart';
Ensure an
AuthHttpServiceis available from your app’s service locator. Stores obtain it via:dart // ModelCreator uses ServiceManager.I.get() under the hood // Provide an implementation of HttpService that performs authenticated HTTP requests.
Fetch all with optional filter:
dart final users$ = UserStore.instance.getAll$( modelFilter: ModelFilter([ LogicalFilterGroup([ PropertyFilter<User, String>( property: 'email', operatorsAndValues: [FilterOperatorAndValue(FilterOperator.contains, '@gmail.com')], ), PropertyFilter<User, int>( property: 'age', operatorsAndValues: [FilterOperatorAndValue(FilterOperator.gte, 18)], ), ], logicalOperator: LogicalOperator.AND), ]), );
Fetch by property value (unique vs many):
dart // Unique field → T? final alice$ = UserStore.instance.getByEmail$('[email protected]');
// Non-unique field → List final adults$ = UserStore.instance.getByAge$(18);
Include relation fields in the response:
dart final postWithAuthor$ = PostStore.instance.getById$( 42, includes: [ PostInclude.author(modelFilter: ModelFilter([ /* ... */ ])), PostInclude.comments(), ], );
All store stream helpers dedupe and cache results, and upsert into their in-memory store automatically.
How stores call the backend (with NestJS generator)
- Each
<Model>Storecontains a<Model>Endpointsenum. Entries match the NestJS generator’s routes:getAll→POST /modelgetBy<Field>/getManyBy<Field>→POST /model/by<Field>/:field- relation list id queries →
POST /model/by<FieldName>Ids/:fieldNameIds
- Stream methods call
AuthHttpService.request(endpoint, param: ..., body: { modelFilter }). - If you also enable
GenerateEndpointsthe generator writes a globalAbc3Routeenum that lists all routes discovered in the backend (useful for custom calls beyond the stores).
Model filter JSON shape
Stores serialize filters into the same logical structure expected by the NestJS services:
json { "modelFilter": { "AND": [ { "age": { "gte": 18 } } ], "OR": [ { "email": { "contains": "@gmail.com" } } ] } }
Contributing
Small parts of this code come from a fork of prisma-utils by Johannes Schobel. If you'd like to contribute, just fork the project and make a pull request.
Building
Run pnpm build from the repo root to build the library.
