Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 1 addition & 22 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ jobs:
run: dart analyze --fatal-infos .

- name: Setup Supabase CLI
if: ${{ matrix.package.backend || matrix.package.name == 'supabase_typegen' }}
if: ${{ matrix.package.backend }}
uses: supabase/setup-cli@45a513f8c64c0bc8e0e3dfe572b5c95be85f6359 # v3.0.1
with:
version: 2.120.0
Expand Down Expand Up @@ -191,29 +191,8 @@ jobs:
docker save "$image" -o "/tmp/supabase-images/${file}.tar"
done

# Port 14432 sits next to the test stack's 14420 to 14429 block, below
# Linux's default ephemeral port range, so an outgoing connection the
# runner opens while the container starts cannot claim it first.
- name: Start Postgres for the typegen parity test
if: ${{ matrix.package.name == 'supabase_typegen' }}
run: |
docker run --detach --name supabase_typegen_parity \
--env POSTGRES_PASSWORD=postgres --publish 14432:5432 postgres:15 \
-c autovacuum=off
for _ in $(seq 1 30); do
if docker exec supabase_typegen_parity pg_isready --host localhost --username postgres; then
exit 0
fi
sleep 1
done
echo "Postgres did not become ready in time." >&2
docker logs supabase_typegen_parity
exit 1

- name: Run tests
working-directory: packages/${{ matrix.package.name }}
env:
SUPABASE_TYPEGEN_PARITY_DATABASE_URL: ${{ matrix.package.name == 'supabase_typegen' && 'postgresql://postgres:postgres@localhost:14432/postgres?sslmode=disable' || '' }}
run: |
CONCURRENCY=""
if [ "${{ matrix.package.concurrency }}" = "1" ]; then
Expand Down
49 changes: 0 additions & 49 deletions .github/workflows/typegen-drift.yml

This file was deleted.

15 changes: 6 additions & 9 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2367,20 +2367,17 @@ create table books (

### Generate the table definitions

Add `supabase_typegen` as a dev dependency and run it against your database. With `--local` it reads
the database of the running local stack, which the Supabase CLI builds from the migrations in your
`supabase/` directory:
Add `supabase_typegen` as a dev dependency and generate the types with the Supabase CLI. With
`--local` it reads the database of the running local stack, which the CLI builds from the
migrations in your `supabase/` directory:

```sh
dart pub add dev:supabase_typegen
dart run supabase_typegen --local
supabase gen types --lang dart --local > lib/supabase_schema.g.dart
```

This writes `lib/supabase_schema.g.dart`. `--linked`, `--project-ref` and `--db-url` generate from
a hosted project instead; see the
[`supabase_typegen` README](packages/supabase_typegen/README.md) for every option. Once the Supabase
CLI ships Dart support, `supabase gen types --lang dart --local > lib/supabase_schema.g.dart`
replaces the direct connection.
`--linked` and `--project-id` generate from a hosted project instead; see the
[`supabase_typegen` README](packages/supabase_typegen/README.md) for details.

For every table the file holds a row type (`BooksRow`), an insert type (`BooksInsert`), an update
type (`BooksUpdate`), and a class (`Books`) with the table definition and one constant per column
Expand Down
96 changes: 24 additions & 72 deletions packages/supabase_typegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,93 +68,45 @@ its `condition` enum `InventoryCondition`.

## Usage

Add `supabase_typegen` as a dev dependency of your project and run it with
`dart run supabase_typegen`, or install it globally with
`dart install supabase_typegen` and run it as `supabase_typegen`. The tool
connects through the
[Supabase CLI](https://supabase.com/docs/guides/cli/getting-started), so have
it installed and, for hosted projects, logged in with `supabase login`. Then
point it at your database:
Add `supabase_typegen` as a dev dependency of your project and generate the
types with the
[Supabase CLI](https://supabase.com/docs/guides/cli/getting-started), from
the project directory:

```sh
dart pub add dev:supabase_typegen

# The database of the running local Supabase stack (`supabase start`).
dart run supabase_typegen --local
supabase gen types --lang dart --local > lib/supabase_schema.g.dart

# The project linked with `supabase link`, or any project by ref.
dart run supabase_typegen --linked
dart run supabase_typegen --project-ref abcdefghijklmnopqrst

# Any Postgres database.
dart run supabase_typegen --db-url 'postgresql://postgres:…@db.…supabase.co:5432/postgres'
supabase gen types --lang dart --linked > lib/supabase_schema.g.dart
supabase gen types --lang dart --project-id abcdefghijklmnopqrst > lib/supabase_schema.g.dart
```

All of them write `lib/supabase_schema.g.dart`; pass `--output` to change the
path or `--output -` to print the code. The types reflect the current state
of the database: with `--local` the SQL in your `supabase/` directory stays
the single source of truth, since the CLI applies your migrations to the
local database and this tool generates from the result, while the other
modes generate from whatever that database currently contains. The code is
formatted with the `dart format` of the SDK running the tool, for the language
version of the project it is written into (the lower bound of the
`environment.sdk` constraint of the nearest `pubspec.yaml`), so `dart format`
in that project leaves it unchanged; with `--output -` the project of the
current directory decides.

`--linked` and `--project-ref` reach the database through the Management API
with your `supabase login` credentials, so no database password is needed;
`--project-ref` needs a CLI that accepts it on `db query` (2.116 or newer),
older ones want `supabase link --project-ref <ref>` followed by `--linked`.
`--db-url` is handed to the CLI as is; it requires TLS unless the connection
string says `sslmode=disable`.

The schemas are chosen the way `supabase gen types` chooses them: `public`
plus the `api.schemas` of the project's `supabase/config.toml`, found under
`SUPABASE_WORKDIR` or by walking up from the working directory, so the
exposed schemas of the project are generated. Pass `--schema` to name the schemas yourself, repeated
or comma separated (`--schema public,inventory`). Only schemas exposed through
the Data API can be queried at runtime. The generated file imports
The CLI introspects the database into the `GeneratorMetadata` document of
[`@supabase/postgrest-typegen`](https://github.com/supabase/sdk/tree/main/packages/postgrest-typegen),
the intermediate representation its TypeScript, Go, Swift and Python
generators consume, and pipes it into this package, which generates the Dart
code from it. Pass `--schema` to choose the schema to generate. Only schemas
exposed through the Data API can be queried at runtime. With `--local` the SQL in your `supabase/` directory
stays the single source of truth, since the CLI applies your migrations to the
local database and generates from the result.

The code is formatted with the `dart format` of the SDK running the tool, for
the language version of the project it is written into (the lower bound of
the `environment.sdk` constraint of the nearest `pubspec.yaml`), so
`dart format` in that project leaves it unchanged. The generated file imports
`PostgrestTable` and `PostgrestColumn` from the library of `supabase_flutter`,
`supabase` or `postgrest`, preferred in that order, that the `pubspec.yaml`
nearest to the output lists under `dependencies`, and from `package:postgrest`
when it lists none of them. Use `--import` to import them from another library.

### How it works

The tool introspects the database with a Dart port of the introspection of
[`@supabase/postgrest-typegen`](https://github.com/supabase/sdk/tree/main/packages/postgrest-typegen)
into the `GeneratorMetadata` intermediate representation its TypeScript, Go,
Swift, and Python generators consume, ordered with `sortGeneratorMetadata`,
and generates the Dart code from that document. The queries run through
`supabase db query`, so the CLI resolves and authenticates the connection.
The port is pinned to a revision of the TypeScript package and produces a
document with the same records; `--dump-metadata` prints it instead of the
generated code, which helps when reporting a generator issue.

The built-in introspection, and with it the `--local`, `--linked`,
`--project-ref`, `--db-url` and `--dump-metadata` options, is a stopgap. It
will be removed once the Supabase CLI ships Dart support for
`supabase gen types`, which then becomes the only way to run this tool; see
the next section.
lists under `dependencies`, and from `package:postgrest` when it lists none of
them.

The metadata comes from the database catalog, so nullability, database
defaults, and identity columns are exact: a `NOT NULL` column with a default
reads as non-nullable but stays optional on insert, and `GENERATED ALWAYS`
columns appear in the row type but not in the insert and update types.

### Through the Supabase CLI

Once `supabase gen types` ships a Dart language, the CLI will run the same
introspection in-process and hand the document to this tool over stdin. The
direct connection modes above will be removed in the release that follows, so
prefer the CLI as soon as it is available:

```sh
supabase gen types --lang dart --local > lib/supabase_schema.g.dart
```

Reading the document from stdin is what the tool does when no connection
option is given, so that path already works with a hand-built document.

## Generated code in action

```dart
Expand Down
Loading
Loading