Skip to content

fix(cli): follow views in the extra search path schemas in gen types - #7515

Merged
jgoux merged 4 commits into
developfrom
fix/gen-types-extra-search-path
Nov 5, 2026
Merged

jgoux merged 4 commits into
developfrom
fix/gen-types-extra-search-path

Conversation

@jgoux

@jgoux jgoux commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

PostgREST derives a view's relationships by following views in the exposed schemas and in db-extra-search-path. gen types only followed the generated schemas. When a view chain passed through an extra search path schema, its relationships were lost, so the types rejected embeds that work at runtime.

create schema api;
create schema extra;   -- [api].extra_search_path = ["extra"]
create table api.accounts (id int primary key);
create table private.invoices (
  id int primary key,
  account_id int not null references api.accounts (id)
);
create view extra.invoices as select * from private.invoices;
create view api.invoices   as select * from extra.invoices;
flowchart LR
  V["api.invoices<br/>(generated)"] --> E["extra.invoices<br/>(extra search path)"] --> T["private.invoices<br/>(FK → api.accounts)"]
Loading

supabase gen types --schema api, Views.invoices.Relationships:

// before
Relationships: []

// after
Relationships: [
  {
    foreignKeyName: "invoices_account_id_fkey"
    columns: ["account_id"]
    referencedRelation: "accounts"
    referencedColumns: ["id"]
  },
]

Change

  • Bump @supabase/typegen to 0.3.2 (postgrest-typegen 0.7.0, feat(postgrest-typegen): follow views in extra search path schemas sdk#329), which takes an extraSearchPath option.
  • Every path that introspects the database passes [api].extra_search_path: --local, --remote=<db-url>, and remote projects or branches with a non-TypeScript --lang. For a project ref, the matching [remotes] block applies, like it does for [api].schemas.
  • The setting is read even with --schema, because it describes the target's PostgREST, not which schemas to generate. Without a config.toml, the default public, extensions applies.
  • Nothing in the extra search path schemas is generated unless --schema or [api].schemas names it.
  • Linked TypeScript generation runs on the Management API and is unchanged.

PostgREST follows views in db-extra-search-path to find a view's base
tables. Pass [api].extra_search_path to typegen so generated view
relationships match what PostgREST embeds at runtime.
@jgoux
jgoux requested review from a team and supabase-oss as code owners November 5, 2026 13:38
@jgoux jgoux self-assigned this Nov 5, 2026
@jgoux
jgoux requested a review from Coly010 November 5, 2026 13:38
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

CLI benchmark (Lightweight Commands): no changes found

Commit efdcb0e against develop at 3217fb4 · 10 runs each · report only, never blocks merging

Command Workload Before After Change
supabase --version version 445 ms 453 ms no real change
supabase --help help 403 ms 427 ms no real change (+6%, within normal variation)
supabase init init 462 ms 429 ms no real change (-7%, within normal variation)
supabase migration new bench migration-new 417 ms 431 ms no real change
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 362 ms 365 ms no real change
supabase projects list projects-list 387 ms 362 ms no real change (-7%, within normal variation)
supabase functions list --project-ref replayfixtureprojref functions-list 383 ms 406 ms no real change (+6%, within normal variation)

API calls: unchanged for all 7 commands.

Binary size: 134.7 MB, up 8.0 KB from 134.7 MB.

Details: timing ranges, API calls per command, slowest phases

Timing ranges

Command Workload Before range After range Change Verdict
supabase --version version 296-544 ms 315-609 ms +8 ms (+2%) within noise
supabase --help help 343-533 ms 351-559 ms +24 ms (+6%) within noise
supabase init init 337-517 ms 359-503 ms -33 ms (-7%) within noise
supabase migration new bench migration-new 298-566 ms 274-620 ms +14 ms (+3%) within noise
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 282-577 ms 308-449 ms +3 ms (+1%) within noise
supabase projects list projects-list 344-418 ms 291-420 ms -25 ms (-7%) within noise
supabase functions list --project-ref replayfixtureprojref functions-list 333-555 ms 288-470 ms +23 ms (+6%) within noise

API calls per command

Command Workload Before After Endpoint changes
supabase --version version 0 0
supabase --help help 0 0
supabase init init 0 0
supabase migration new bench migration-new 0 0
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 2 2
supabase projects list projects-list 1 1
supabase functions list --project-ref replayfixtureprojref functions-list 2 2

Slowest phases

No command moved beyond noise, so there are no phase deltas.

Workflow run

Comment /bench to run the lightweight benchmark (this comment) again on the latest commit, or /bench full to also run the integration-heavy benchmark, which posts in its own comment.

Read [api].extra_search_path before any API call or connection, share the
config load with the legacy local path, and cover the preview branch path.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Reconciled all five findings. Four are confirmed, with the config-bypass regression narrowed to preview-branch fallback and the coverage finding narrowed to missing assertions. The repeated-parsing claim is refuted because config loading is cached. Both independent reviews were available.

Findings

Severity Location Category Sources Claim
🟡 MINOR apps/cli/src/commands/gen/types/types.handler.ts:529 error-handling claude Preview-branch generation with an explicit --schema now loads the full local config through resolveExtraSearchPath. A malformed or duplicate-remote config can therefore abort an invocation that previously bypassed config loading. The comment at line 315 still claims --schema skips the config load.
🟡 MINOR apps/cli/src/commands/gen/types/types.handler.ts:459 correctness claude Hosted project and preview-branch introspection use the resolved local extra search path rather than the hosted PostgREST setting. When those values differ, introspection can derive relationship metadata using a search path that the hosted API does not use.
⚪ NIT apps/cli/src/commands/gen/types/types.integration.test.ts:1000 test-coverage claude The new tests do not assert extraSearchPath on preview-branch fallback or pin the outcome of --schema combined with invalid or duplicate-remote config.
⚪ NIT apps/cli/src/commands/gen/types/types.handler.ts:263 naming codex The new loadProjectConfig helper uses the hosted-config name for a local CliConfig loader, contrary to ADR 0020.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/src/commands/gen/types/types.handler.ts:743 (performance): Without --schema, URL and linked generation load and parse the project config twice for schemas and extraSearchPath, with a third load on the local legacy path.
    Refuted: Repeated calls do not imply repeated parsing. cli-config-values.layer.ts:612-633 caches successful resolved configs indefinitely using structural LoadKey values. The schema and extra-search-path helpers pass identical keys. Additionally, :242-256 caches parsed documents by workdir, including across loads with different tolerance options. Sharing a resolved value could simplify the handler, but the claimed repeated-parsing cost is absent.

Stats

Claude findings: 4 · Codex findings: 1 · Confirmed: 4 · Refuted: 1 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

…e source

Rename the config loader to the CliConfig vocabulary, test that a malformed config
fails before any API call even with --schema, and document that remote projects read
the extra search path from config.toml rather than the hosted setting.

@Coly010 Coly010 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! Ran it against a local Postgres with the api -> extra -> private view chain and Views.invoices.Relationships now has the fkey (empty on develop).

Not a blocker, but linked TS generation still goes through the Management API, so --linked won't pick this up. Might be worth a follow-up if we want it there too.

Check code quality failed on a mise download (curl 22), so it just needs a re-run.

@jgoux
jgoux added this pull request to the merge queue Nov 5, 2026
Merged via the queue into develop with commit d3c5cb0 Nov 5, 2026
49 checks passed
@jgoux
jgoux deleted the fix/gen-types-extra-search-path branch November 5, 2026 19:31
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.

2 participants