Skip to content

feat(gen): add dart and json output languages to gen types - #6230

Closed
spydon wants to merge 4 commits into
developfrom
feat/gen-types-json-dart
Closed

spydon wants to merge 4 commits into
developfrom
feat/gen-types-json-dart

Conversation

@spydon

@spydon spydon commented Aug 17, 2026

Copy link
Copy Markdown

Summary

Adds two --lang values to supabase gen types, making supabase gen types --lang dart work end to end:

  • json: passes the language-neutral GeneratorMetadata introspection document (the @supabase/postgrest-typegen contract) 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 the json generator, collects the metadata instead of printing it, and pipes it through dart 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 the supabase_typegen package 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:

Implementation notes:

  • The lang additions are TS-only and documented in docs/go-cli-divergences.md; SIDE_EFFECTS.md covers the new dart subprocess and the json-collection behavior.
  • The invocation contract (dart run supabase_typegen --input - --output -) is pinned in types.shared.ts so the handler and tests share one definition.
  • Integration tests cover the json passthrough 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 #

  • The linked issue is open and carries the open-for-contribution label (or I'm a Supabase maintainer).

Checklist

  • The PR title follows Conventional Commits (e.g. fix(cli): …).
  • Tests added or updated for the change.
  • pnpm check:all and pnpm test pass for the workspace(s) I touched (check:all fully; unit and integration suites for gen types pass, the docker-dependent e2e suite was not run locally).

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.
@spydon

spydon commented Sep 1, 2026

Copy link
Copy Markdown
Author

Superseded by the native typegen architecture in #6404: the CLI holds the sorted GeneratorMetadata in-process there, so --lang dart can hand the document to the Dart generator directly and no pg-meta container or user-facing --lang json is needed. A small follow-up on top of #6404 will add the dart flag.

@spydon spydon closed this Sep 1, 2026
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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant