Conversation
This was referenced Aug 17, 2026
feat: add supabase_typegen package generating typed table definitions
supabase/supabase-flutter#1635
Merged
lvinist
added a commit
to lvinist/mine-flow-app
that referenced
this pull request
Aug 25, 2026
… harden guard - Remove lib/core/data/models/generated/database.dart (10-line hand-written stub of empty classes; Dart typegen was removed from the Supabase CLI — supabase/cli#6230 to restore it is still a draft) - Add supabase/types/database.ts: real 'supabase gen types --lang typescript' output against staging (714 lines, all 9 tables + enums), now the committed contract artifact per Option 1 decision - Harden tool/check_supabase_contracts.dart: reject artifacts missing the 'export type Database' / '__InternalSupabase' typegen markers or under a minimum size (stub class of phantom close); repoint all paths - Update guard tests: +stub-rejection case, artifact helpers; 4/4 pass Verification: dart run tool/check_supabase_contracts.dart exit 0; flutter test 435/435 (was 434); flutter analyze 0 issues.
Author
|
Superseded by the native typegen architecture in #6404: the CLI holds the sorted GeneratorMetadata in-process there, so |
spydon
added a commit
to supabase/supabase-flutter
that referenced
this pull request
Sep 1, 2026
…#1635) ## What kind of change does this PR introduce? Feature (draft, layer 2 of the typed table access work, stacked on #1634). Adds a new `supabase_typegen` package: a standalone code generator that turns a database schema into the typed table definitions introduced in #1634, so users get the fully typed surface without writing any of it by hand. Linear: SDK-1362 ## What is the new behavior? ```sh supabase gen types --lang dart --local > lib/supabase_schema.g.dart ``` The CLI runs postgrest-typegen's introspection in-process against the database and hands the language-neutral `GeneratorMetadata` document, the intermediate representation of [`@supabase/postgrest-typegen`](https://github.com/supabase/sdk/tree/main/packages/postgrest-typegen) that its TypeScript, Go, Swift, and Python generators also consume, to this tool over stdin. The tool emits one Dart file containing, per table: - a zero-cost row extension type over the decoded JSON map with typed getters (`DateTime` parsing, `double`/`num` coercion, `List` casts, Postgres enum mapping), - `Insert` and `Update` value extension types that implement `Map<String, dynamic>`, with required parameters derived from `NOT NULL`-without-default columns and null-aware omission for everything else; explicit SQL NULL writes go through generated `set…ToNull` copy methods that only exist for nullable, writable columns, - a `PostgrestTable` definition plus `TableColumn` tokens for compile-time checked filters, - Dart enums for Postgres enums with wire-name mapping (`toString` returns the wire name so enum values work directly in filters). See `packages/supabase_typegen/test/goldens/supabase_schema.dart` for what the output looks like for the fixture schema. Design choices worth reviewing: - **Introspection source**: the `GeneratorMetadata` contract of `@supabase/postgrest-typegen` (version 1, as shipped in the released 0.2.0 and embedded in postgres-meta v0.99.0). The CLI produces the document by running the package's `introspect()` in-process against the local database; there is no postgres-meta dependency. The document comes straight from the database catalog, so the output is exact where API-derived descriptions are lossy: `NOT NULL` columns with a database default read as non-nullable but stay optional on insert, identity columns are recognized, and `GENERATED ALWAYS` columns appear in the row type but are excluded from the insert and update types. Structural validation rejects non-matching documents. - **Relation and column writability**: tables and foreign tables emit the full surface; views gate `Insert` and `Update` independently on `is_insert_enabled` and `is_update_enabled` (falling back to `is_updatable` for documents predating the flags), so a view writable only through an INSTEAD OF INSERT trigger gets exactly an insert type; materialized views are read-only; non-updatable view columns read but are excluded from writes. This mirrors the TypeScript generator's semantics. - **Exact enum resolution**: a column's enum type resolves by its `type_schema` plus type name, so same-named enums in different schemas cannot be confused. - **Canonical ordering**: columns are emitted in the order `sortGeneratorMetadata` produces (name order within a table), matching every other postgrest-typegen generator and keeping output insensitive to column declaration order. - **Naming**: `books` emits `BooksRow`/`BooksInsert`/`BooksUpdate` plus a `Books` namespace class (no English singularization, so names stay predictable). Identifiers are sanitized against Dart reserved words and `Map` member names with a `$` suffix, and collisions are deduplicated. - **Lint-clean output**: the emitted code (checked in as a golden) passes `supabase_lints` and DCM with zero issues, including the strict extension type rules. ## Additional context - The metadata fixture is regenerated from a real introspection and stays reproducible: `test/fixtures/seed.sql` applied to a disposable Postgres container, introspected with the released `@supabase/postgrest-typegen@0.2.0` via `tool/regenerate_fixture.ts`. - CLI exposure as `supabase gen types --lang dart` is a small follow-up on supabase/cli#6404, which already runs postgrest-typegen's `introspect()` in-process: the CLI serializes the sorted document and pipes it to `dart run supabase_typegen` over stdin, the tool's only input channel. No pg-meta container, no metadata file on disk, and no user-facing json output language are involved (the earlier container-based supabase/cli#6230 is closed as superseded). - The package is excluded from the SDK compliance scan via `.sdk-parse-ignore` since it is a development-time tool, not SDK client surface; the symbol, drift and schema checks pass locally against the base branch. - `supabase_typegen` is added to the CI dart test matrix; tests are fully mocked/fixture-based (introspection unit tests over the checked-in metadata fixture, a whitespace-insensitive golden comparison with a `tool/regenerate_goldens.dart` refresh script, and behavior tests that run the generated golden code against a mock HTTP client to verify wire formats end to end). - `publish_to: none` until the API settles. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a Dart generator for strongly typed Supabase tables, rows, inserts, updates, columns, relationships, views, and Postgres enums. * Added the `supabase_typegen` command-line tool, accepting metadata through standard input and writing generated code to the terminal or a file. * Added safe handling for dates, timestamps, enums, arrays, comments, and reserved identifiers. * **Documentation** * Updated usage guidance, schema-target behavior, generated-code examples, options, and limitations. * **Tests** * Added comprehensive coverage for generation, parsing, serialization, views, relationships, enums, and typed data access. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
spydon
added a commit
to supabase/supabase-flutter
that referenced
this pull request
Sep 15, 2026
…CLI (#1837) ## Summary `supabase_typegen` could only read a `GeneratorMetadata` document on stdin and relied on `supabase gen types --lang dart` to produce it, which has not shipped (supabase/cli#6230 was closed and supabase/cli#6404 carries no Dart path). This adds a Dart port of the introspection of [`@supabase/postgrest-typegen`](https://github.com/supabase/sdk/tree/main/packages/postgrest-typegen), pinned to `postgrest-typegen-v0.2.2`, so the tool can produce the document itself. The database connection is delegated to the Supabase CLI: ```sh dart run supabase_typegen --local dart run supabase_typegen --linked dart run supabase_typegen --project-ref <ref> dart run supabase_typegen --db-url 'postgresql://…' dart run supabase_typegen --local --dump-metadata ``` Stdin stays the default when no target is given, so the eventual CLI integration is untouched. Everything new lives under `lib/src/introspection/`, `lib/introspection.dart`, `test/introspection/`, the tool scripts and the drift workflow, and the README states that it will be removed once the CLI ships Dart support. ## How it connects The eleven introspection queries are folded into one `SELECT` with a `json_agg` sub-select per collection and run through a single `supabase db query --output json --file <statement>` call. The CLI resolves and authenticates the connection: `--local` uses the running stack, `--linked` and `--project-ref` go through the Management API with the `supabase login` credentials and need no database password, and `--db-url` is passed straight through. The package has no database driver; `postgres` is only a dev dependency for seeding the parity database. Failures produce actionable messages: the CLI missing from `PATH` (with the install link), not logged in (`supabase login` or `SUPABASE_ACCESS_TOKEN`), no linked project (`supabase link` or `--project-ref`), and everything else surfaces the CLI's own message with its colour codes and progress line stripped, which already covers "run `supabase start`" and network restriction hints. Passing more than one target is a usage error. ## What is ported - The eleven SQL builders, one file each, taking the schema filter alone, matching the trimmed builders of supabase/sdk#180. The view definition rewrites render from a table, matching supabase/sdk#179. The `pg-format` literal escaping is included for the schema filter. - The view relationship expansion (cartesian product over view key dependencies). - The ordering pass, with a stable merge sort because the TypeScript sort relies on `Array.prototype.sort` being stable for composite primary keys and tied relationships. - `localeCompare` semantics: the ICU root collation for printable ASCII (punctuation, digits, then letters with case as the last tiebreaker, lower case first), verified against Bun and Node. Non-ASCII code units sort after ASCII by code unit, which only affects collection order for accented names. Following 0.2.2 also brings in the changes since 0.2.0: `is_insert_enabled` and `is_update_enabled` on views, trigger and rule backed view columns marked updatable, and virtual generated columns counted as generated. The fixture and goldens are regenerated accordingly; the join view with an `INSTEAD OF INSERT` trigger now gets a `BookSubmissionsInsert` type, and the two tests asserting the old behaviour were updated. ## Verification - Parity test (`test/introspection/parity_test.dart`): seeds a fresh `postgres:15` with `test/fixtures/seed.sql` when the database is empty, introspects it through the CLI unfiltered and restricted to `public`, and asserts the document holds the same records as `test/fixtures/generator_metadata.json`, collection by collection. Records are compared as maps, so key order is irrelevant; record order within a collection is checked since the document is sorted. It also runs the binary and checks `--dump-metadata` yields the fixture records and `--output -` reproduces `test/goldens/supabase_schema.dart`. The test skips unless `SUPABASE_TYPEGEN_PARITY_DATABASE_URL` is set; `test.yml` starts the container and installs the CLI for the `supabase_typegen` matrix entry. - Drift guard (`tool/check_introspection_drift.ts`): fetches the TypeScript builders of the pinned supabase/sdk revision from GitHub, renders every query for three filter scenarios, and compares byte for byte with `dart run tool/dump_introspection_sql.dart`. The new `typegen-drift.yml` runs it on PRs touching the package and weekly against supabase/sdk `main` with `--latest`, so an upstream SQL change surfaces as a failing scheduled run. Bumping the pin is: run the script with `--ref`, port the printed diff, regenerate the fixture with `tool/regenerate_fixture.ts --source <sdk checkout>`, update `postgrestTypegenRevision`. - Unit tests for the literal escaping, the schema filter and builder conditionals, the relationship expansion (ported from upstream), the sort and collation, the document assembly against a fake query runner, and the CLI runner against a fake `supabase` script (flags, JSON parsing, not installed, not logged in). - Manually ran `--local` against the running local stack and the error paths (not logged in, not linked, CLI missing from `PATH`, local stack down, conflicting flags). ## Notes - The direct modes require a Supabase CLI with `db query` (2.116 or newer). `--db-url` against a server without TLS needs `sslmode=disable` in the connection string, as the CLI requires TLS otherwise. - `oven-sh/setup-bun` is a new third-party action, pinned by SHA like the others in this repo. Closes SDK-1834. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added database introspection through local, linked, project-reference, or database URL connections. * Added `--dump-metadata` to output raw generator metadata. * Added flexible output options for writing generated code to a file or standard output. * Improved support for view relationships and insertable views, including generated insert types. * **Documentation** * Updated usage guidance for connection modes, authentication, TLS settings, and output options. * **Bug Fixes** * Improved metadata ordering and relationship handling for more consistent generated output. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds two
--langvalues tosupabase gen types, makingsupabase gen types --lang dartwork end to end:json: passes the language-neutralGeneratorMetadataintrospection document (the@supabase/postgrest-typegencontract) straight through (the same catalog introspection the typescript/go/swift/python generators consume, with exact nullability, defaults, and identity information). This gives third-party and community type generators a single high-fidelity source instead of parsing lossy API descriptions.dart: runs the pg-meta container with thejsongenerator, collects the metadata instead of printing it, and pipes it throughdart run supabase_typegen --input - --output -on the host. The generated Dart code arrives on stdout like every other language; the typegen's summary line goes to stderr. Requires the Dart SDK on PATH and thesupabase_typegenpackage as a dev dependency of the current project; a missing SDK or failing typegen produces an actionable error.Both languages work on every connection path (
--local,--db-url,--linked,--project-id, and the implicit linked fallback), since non-TypeScript languages already run pg-meta directly.Draft because of upstream dependencies:
GeneratorMetadatacontract, and feat: consume @supabase/postgrest-typegen for type generation postgres-meta#1084 makes postgres-meta consume that package; thejsonvalue forPG_META_GENERATE_TYPESis added on top of it in feat: add json output exposing the GeneratorMetadata contract postgres-meta#1110 (stacked on fix: bump edge-runtime to v1.2.19 #1084; It should be possible to run npx supabase init without human interaction #1106 was closed as a duplicate of that stack), and this PR needs a pg-meta image that ships it.supabase_typegenpackage (its--input -/--output -stdin/stdout contract is already in place there).Implementation notes:
docs/go-cli-divergences.md;SIDE_EFFECTS.mdcovers the newdartsubprocess and the json-collection behavior.dart run supabase_typegen --input - --output -) is pinned intypes.shared.tsso the handler and tests share one definition.jsonpassthrough env, the dart pipe (metadata collected rather than printed, dart argv, generated code on stdout), and the non-zero typegen exit error.Linked issue
Closes #
open-for-contributionlabel (or I'm a Supabase maintainer).Checklist
fix(cli): …).pnpm check:allandpnpm testpass for the workspace(s) I touched (check:allfully; unit and integration suites forgen typespass, the docker-dependent e2e suite was not run locally).