feat(postgrest)!: only accept the table's Insert and Update types on the typed builder - #1849
Conversation
…the typed builder PostgrestTable carries Insert and Update type parameters next to Row, and the typed query builder's insert, insertAll, upsert, upsertAll and update methods accept only those types. Read-only relations use Never for the write types they do not support. supabase_typegen emits the type arguments, drops the Map interface from the generated extension types and adds toJson to row types. The untyped update accepts Object like insert.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (24)
Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe PR adds row, insert, and update type parameters to typed PostgREST and Supabase tables and builders. It adds batch insert and upsert methods, passes row converters through builder chains, and updates type generation, generated schemas, tests, and SDK capability metadata. ChangesTyped mutation API
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant Caller
participant SupabaseClient
participant PostgrestTypedQueryBuilder
participant PostgREST
Caller->>SupabaseClient: provide typed PostgrestTable
SupabaseClient->>PostgrestTypedQueryBuilder: create typed builder
Caller->>PostgrestTypedQueryBuilder: call insert, upsert, or update
PostgrestTypedQueryBuilder->>PostgREST: send typed value as request body
PostgREST-->>PostgrestTypedQueryBuilder: return response rows
PostgrestTypedQueryBuilder-->>Caller: convert rows with rowFromJson
Suggested reviewers: Merge Risk: ⚪ Minimal · up to This change tightens the typed database API so insert, upsert, and update calls only accept the value types generated for each table, and adds batch insert and upsert helpers. Generated code and tests were updated consistently, and no outstanding correctness or availability concerns remain, so it is ready to merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…r names in typegen insertAll and upsertAll throw on an empty list, matching the other argument checks on the typed builder. Generated extension types no longer implement Map, so only the Object members need a suffix in generated member names.
…ter (#1850) ## Summary Main does not compile since #1848 and #1849 merged within minutes of each other. #1849 replaced the typed transform builder's `PostgrestTable` field with a `RowConverter<Row>` (`_rowFromJson`), and #1848 added `stripNulls`, `dryRun`, `maxAffected` and `csv` on top of the old field. Neither PR's CI saw the other, so every check on main and on the open PRs fails at compile time in `postgrest_typed_transform_builder.dart`: ``` Error: The getter '_table' isn't defined for the type 'PostgrestTypedTransformBuilder<Row, T>'. ``` ## Changes - The four methods from #1848 pass `_rowFromJson` to the private constructor, like the rest of the class does after #1849. - The two tests from #1848 that passed raw maps use `BookInsert` and `BookUpdate`, which #1849 made the only accepted payload types on the typed builder. - The `dryRun` dartdoc example uses `BookInsert` as well. No public API change. `dart analyze` on `packages` and `examples` is clean, `typed_query_test.dart` passes (49), DCM is clean. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved typed mutation operations so options such as dry runs, affected-row limits, CSV responses, and null stripping consistently preserve the expected result types. - Updated typed insert and update usage in mutation scenarios to ensure submitted data is handled with the correct typed representations. - **Documentation** - Updated the dry-run example to demonstrate usage with a typed insert value. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
client.table(X.table)was typed on the way out but not on the way in:insertandupserttookObjectandupdatetookMap<String, dynamic>, so a payload for the wrong table or with a misspelled column compiled. This closes that gap on the typed surface. The untypedfrom()path keeps accepting raw maps.Changes
PostgrestTable<Row, Insert, Update>carries the write types next to the row type.InsertandUpdateare unbounded on purpose: a bound would make Dart silently infer it when the type arguments are left off, while without onestrict-inferencereports the missing arguments. Hand-written tables spell them out, for examplePostgrestTable<Book, BookInsert, BookUpdate>('books', Book.new). Read-only relations useNever, which makes the write methods uncallable.PostgrestTypedQueryBuilder.insertandupserttake oneInsert, the newinsertAllandupsertAlltake aList<Insert>, andupdatetakesUpdate. Dart has no union types, so single and bulk writes are separate methods, mirroringaddandaddAll.insertAllandupsertAllthrow on an empty list, like the other argument checks on the typed builder. This also closes the one call that still compiled on aNevertable,insertAll([]).RowConverter<Row>instead of the table and keep a singleRowtype parameter.PostgrestQueryBuilder.updateacceptsObjectlikeinsertandupsertalready did, so the typed layer can forward anyUpdatetype. Existing callers are unaffected.supabase_typegenemits the three type arguments on the table constant, withNeverfor relations without an insert or update surface. The generated row, insert and update extension types implementObjectinstead ofMap<String, dynamic>: the map interface let a checkedBooksInsertbe mutated or indexed with arbitrary keys after construction, and let a column named like aMapmember break the generated code. Row types gaintoJson()as the explicit way to get at the decoded map.Objectmembers now. Reserving everyMapmember name was there because the row types implementedMap, so a column calledlengthor a relation to a table calledmapno longer gets a$.PostgrestTypedQueryBuilder.insertAllandupsertAllare registered insdk-compliance.yaml.Testing
packages/postgrest/test/typed_query_test.dartuses hand-writtenBookInsertandBookUpdatetypes, aNevertable for authors, and coversinsertAll,upsertAlland their empty-list checks.packages/supabase_test/test/typed_api_test.dart,packages/supabase/test/mock_test.dartandstream_filter_test.dartdeclare their write types.setXToNullthrough the request body since the update type is opaque.dart analyze,dcm analyzeand the sdk compliance symbol, drift and schema checks pass locally.Closes SDK-1879.
Summary by CodeRabbit
New Features
insertAllandupsertAlloperations, including validation for empty input.toJson()for serialization.Documentation