Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
56a5719
feat(cli): port db dump, query, and schema declarative to native Type…
Coly010 Jun 16, 2026
a9cace6
fix(cli): cache linked project on db query --linked to match Go CLI
Coly010 Jun 16, 2026
3a2bf30
fix(cli): reject mutually-exclusive db flags to match Go CLI
Coly010 Jun 16, 2026
c33f670
fix(cli): keep declarative generate stdout payload-only in JSON mode
Coly010 Jun 16, 2026
6cb867e
fix(cli): serialize pooler options in pg-delta Postgres URLs to match Go
Coly010 Jun 16, 2026
432435e
fix(cli): return the reset failure when declarative sync reset also f…
Coly010 Jun 16, 2026
a7e02f9
fix(cli): honor --network-id and deno_version for pg-delta edge-runtime
Coly010 Jun 16, 2026
e86f08c
fix(cli): use configured local hostname for declarative local URLs
Coly010 Jun 16, 2026
cba59d4
test(e2e): normalize Docker image-pull progress in parity comparisons
Coly010 Jun 16, 2026
f9841b1
fix(cli): honor --yes for declarative generate overwrite prompt
Coly010 Jun 16, 2026
fa34e99
fix(cli): use configured hostname when applying declarative sync migr…
Coly010 Jun 16, 2026
70f76ed
fix(cli): forward --network-id into the declarative catalog seam
Coly010 Jun 16, 2026
e0c1b16
fix(cli): split db dump comma-list flags and resolve --file from workdir
Coly010 Jun 16, 2026
6e37dba
fix(cli): resolve db query --file against the workdir
Coly010 Jun 16, 2026
79135bf
fix(cli): fail unlinked db query --linked instead of prompting
Coly010 Jun 16, 2026
31061b6
fix(cli): parse and normalize smart custom database URLs in declarati…
Coly010 Jun 16, 2026
88d853f
fix(cli): honor --yes and forward --network-id in declarative sync
Coly010 Jun 16, 2026
70238fa
fix(cli): propagate declarative generate reset failures instead of ex…
Coly010 Jun 16, 2026
18d1396
fix(cli): match Go config parity for local password and major_version
Coly010 Jun 16, 2026
834610e
fix(cli): fail unlinked --linked db targets instead of prompting
Coly010 Jun 16, 2026
8921c48
fix(cli): render linked db query JSON values like Go's fmt %v
Coly010 Jun 16, 2026
5d95cb3
fix(cli): cache linked project for db dump / declarative generate tel…
Coly010 Jun 16, 2026
cd688ef
fix(cli): report db query resolved output as the telemetry output_format
Coly010 Jun 16, 2026
96d1856
fix(cli): make --no-cache a shared flag on the db schema declarative …
Coly010 Jun 16, 2026
fa849bd
fix(cli): resolve linked db access token lazily to match Go's passwor…
Coly010 Jun 16, 2026
0e7a0e3
fix(cli): bump native PG image to 17.6.1.136 to match Go Dockerfile
Coly010 Jun 16, 2026
3c333ee
fix(cli): validate experimental.pgdelta.format_options as JSON at con…
Coly010 Jun 16, 2026
0b74646
fix(cli): honor --yes and forward --network-id in smart-generate loca…
Coly010 Jun 16, 2026
2f998cd
fix(cli): format linked db query numeric cells with Go float64 %g
Coly010 Jun 16, 2026
486d5d9
fix(cli): add Linux host-gateway mapping to pg-delta edge-runtime con…
Coly010 Jun 16, 2026
7a94328
fix(cli): offer the linked project in declarative smart generate
Coly010 Jun 16, 2026
3db4de4
fix(cli): retry linked db dump through the IPv4 pooler on container I…
Coly010 Jun 16, 2026
209ea58
fix(cli): honor --yes for the declarative smart-generate regenerate p…
Coly010 Jun 16, 2026
1f9db74
fix(cli): build db query runtime without eager Management API auth
Coly010 Jun 16, 2026
9c39e9f
fix(cli): start the local stack before local declarative generate
Coly010 Jun 16, 2026
f4ff6c9
fix(cli): run declarative sync bootstrap through the smart-generate flow
Coly010 Jun 16, 2026
5528584
fix(cli): apply matching [remotes.<ref>] config override on the linke…
Coly010 Jun 16, 2026
5e5d8f1
fix(cli): fetch primary pooler config from API in dump fallback when …
Coly010 Jun 16, 2026
bb766d7
fix(cli): forward --network-id when auto-starting the local stack
Coly010 Jun 16, 2026
53fbde6
fix(cli): read merged dump config before opening --file
Coly010 Jun 16, 2026
0eb7057
fix(cli): resolve debug-bundle catalog refs against the workdir
Coly010 Jun 16, 2026
b7874e1
fix(cli): run the linked db query login preflight before reading SQL
Coly010 Jun 16, 2026
9d8c568
fix(cli): derive local stack container id from config project_id
Coly010 Jun 16, 2026
1666508
fix(cli): reject invalid edge_runtime.deno_version at config load
Coly010 Jun 16, 2026
255f64f
fix(cli): write db dump stdout byte-for-byte to preserve non-UTF-8 dumps
Coly010 Jun 16, 2026
abc33fc
fix(cli): start only the database (db start) during declarative auto-…
Coly010 Jun 16, 2026
3bed770
fix(cli): include failing statement context on migration apply errors
Coly010 Jun 16, 2026
80ea7f7
fix(cli): render local db query float4/float8 cells with Go's %g
Coly010 Jun 16, 2026
06ae76e
fix(cli): apply [remotes.<ref>] override for explicit --linked declar…
Coly010 Jun 16, 2026
21fa228
fix(cli): gate linked declarative generate on base config, not the re…
Coly010 Jun 16, 2026
0653d81
fix(cli): reject duplicate remote project_id and honor pg-delta env o…
Coly010 Jun 16, 2026
9cced11
fix(cli): render local db query timestamp and multiline cells like Go
Coly010 Jun 16, 2026
b3df9f4
fix(cli): emit local int8/bigint as JSON numbers (lossless) to match Go
Coly010 Jun 16, 2026
562e9ed
fix(db): render bytea cells like Go's []byte for db query (review: 34…
Coly010 Jun 16, 2026
d745378
fix(config): validate db.major_version strings and honor deno_version…
Coly010 Jun 16, 2026
3039366
fix(db): keep edge-runtime stderr buffered, tee only for db dump (rev…
Coly010 Jun 16, 2026
395d814
fix(db): don't report unsaved declarative debug bundles (review: 3423…
Coly010 Jun 16, 2026
e087bff
fix(db): preserve timestamp microseconds in db query output (review: …
Coly010 Jun 16, 2026
e1d70a1
fix(config): strict deno_version parse + validate remote project_id (…
Coly010 Jun 16, 2026
add1aa2
fix(db): match Go db query JSON output for bigint, column order, non-…
Coly010 Jun 16, 2026
d56eb58
fix(db): validate merged dump config before --dry-run (review: 342426…
Coly010 Jun 16, 2026
2dc88f1
fix(db): warm declarative catalog cache after generate (review: 34242…
Coly010 Jun 16, 2026
4e8aa17
fix(db): resolve query db config before reading SQL (review: 3424266219)
Coly010 Jun 16, 2026
8aa9db0
fix(db): don't warm declarative cache for a remote-overridden path (r…
Coly010 Jun 16, 2026
ca0eb3e
fix(db): honor SUPABASE_PROJECT_ID for the local db container check (…
Coly010 Jun 16, 2026
f35159f
fix(db): validate linked query config before the API call (review: 34…
Coly010 Jun 16, 2026
2d7d4f0
fix(config): parse enabled bools via Go strconv.ParseBool (review: 34…
Coly010 Jun 16, 2026
2336962
fix(db): use absolute declarative_schema_path as-is (review: 3424613515)
Coly010 Jun 16, 2026
32e8570
fix(db): preserve Go map key order for integer-like JSON columns (rev…
Coly010 Jun 17, 2026
f249222
fix(db): reject multi-statement db query like Go's pgx (review: 34247…
Coly010 Jun 17, 2026
ee47c54
fix(db): keep the original dump error when pooler fallback fails (rev…
Coly010 Jun 17, 2026
ab30a30
fix(db): preserve sub-100 years + dedupe duplicate JSON columns in db…
Coly010 Jun 17, 2026
9e46697
fix(db): drop named volumes under Bitbucket Pipelines (review: 342494…
Coly010 Jun 17, 2026
eed3384
fix(db): measure db query table cells by rune width (review: 3424266207)
Coly010 Jun 17, 2026
9abc429
fix(db): forward all Postgres RuntimeParams to pg-delta (review: 3424…
Coly010 Jun 17, 2026
ecb5fa0
fix(db): resolve edge-runtime image from merged linked config in decl…
Coly010 Jun 17, 2026
5edfab9
fix(db): probe TLS for non-Supabase pg-delta remotes to match Go isRe…
Coly010 Jun 17, 2026
207fd5b
fix(db): stream db dump output to destination to match Go StdCopy (re…
Coly010 Jun 17, 2026
862dfc5
Merge branch 'develop' into cli/port-db-dump-query-schema-commands
Coly010 Jun 17, 2026
7899dfc
fix(db): wire LegacyIdentityStitch into dump/query/declarative runtim…
Coly010 Jun 17, 2026
72d9e6d
fix(db): cache linked project in command post-run, not mid-resolve (c…
Coly010 Jun 17, 2026
1cd32b7
fix(db): strip IPv6 brackets before pg-delta SSL probe to match Go (r…
Coly010 Jun 17, 2026
9612299
fix(db): preserve negative zero in db query output to match Go (revie…
Coly010 Jun 17, 2026
1a5eaef
fix(db): fail on unreadable migrations dir to match Go ListLocalMigra…
Coly010 Jun 17, 2026
b15e319
fix(db): CSV-split declarative --schema like Go StringSliceVarP (revi…
Coly010 Jun 17, 2026
3a540ce
fix(db): treat db query --linked=false as explicit linked target to m…
Coly010 Jun 17, 2026
c3979b5
fix(db): expand env() in project_id before validation and Docker ID d…
Coly010 Jun 17, 2026
41f46d9
fix(db): forward db-url runtimeParams to live connections via libpq o…
Coly010 Jun 17, 2026
5b16ca8
fix(db): honor OrioleDB image override and S3 env warning to match Go…
Coly010 Jun 17, 2026
59cf01b
fix(db): validate ref-merged linked config before network work to mat…
Coly010 Jun 17, 2026
fdb2214
style(db): apply oxfmt line-wrapping to db config/query test edits
Coly010 Jun 17, 2026
c580ef7
fix(db): CSV-parse db dump --schema/--exclude like Go StringSliceVarP…
Coly010 Jun 17, 2026
9d52817
fix(db): treat declarative generate --linked/--local=false as explici…
Coly010 Jun 17, 2026
86dac07
fix(db): merge pg_service.conf + PGAPPNAME settings into runtimeParam…
Coly010 Jun 17, 2026
a48be9c
fix(db): carry client sslcert/sslkey TLS auth from db-url to match pg…
Coly010 Jun 17, 2026
9c3376e
style(db): apply oxfmt line-wrapping to db config/connection edits
Coly010 Jun 17, 2026
c5f5627
fix(db): build linked generate baseline from remote-merged config via…
Coly010 Jun 17, 2026
a255182
Merge remote-tracking branch 'origin/develop' into cli/port-db-dump-q…
Coly010 Jun 17, 2026
19e2a83
test(cli): add rawBytes to issue Output mocks after merging develop (…
Coly010 Jun 17, 2026
24b2e35
fix(db): gate declarative generate local auto-start on flag value not…
Coly010 Jun 17, 2026
d8e7b33
fix(db): report db dump shorthand flags under canonical names in tele…
Coly010 Jun 17, 2026
27638a6
fix(db): resolve linked DB config before db query API call to match G…
Coly010 Jun 17, 2026
6fd7bbd
fix(db): cache linked project after declarative generate to match Go …
Coly010 Jun 17, 2026
6ed3cee
style(db): apply oxfmt formatting to generate handler
Coly010 Jun 17, 2026
2cc1855
fix(db): count db query --local presence in target mutex to match Go …
Coly010 Jun 17, 2026
f5df853
fix(db): gate db dump flag mutex and target selection on presence to …
Coly010 Jun 17, 2026
6e609e2
fix(db): count declarative sync --apply/--no-apply presence in mutex …
Coly010 Jun 17, 2026
c40eb67
style(db): apply oxfmt to query/dump/sync flag-mutex test edits
Coly010 Jun 17, 2026
1621fc3
chore(cli-go): regenerate API client from upstream spec (ci: Codegen)
Coly010 Jun 17, 2026
1ef8fa3
fix(db): never abort the temp-role retry on an unban failure to match…
Coly010 Jun 17, 2026
3c607ab
fix(db): satisfy db dump data-only required check on flag presence to…
Coly010 Jun 17, 2026
d9e8265
fix(db): keep debug-bundle migration listing from masking the primary…
Coly010 Jun 17, 2026
b4de984
fix(db): warm declarative catalog in sync bootstrap before diff to ma…
Coly010 Jun 17, 2026
e0208a8
style(db): apply oxfmt to dump/debug-bundle test edits
Coly010 Jun 17, 2026
357bf83
fix(db): resolve linked query config before the token preflight to ma…
Coly010 Jun 17, 2026
e6a171e
fix(db): validate storage bucket names on config load to match Go (re…
Coly010 Jun 17, 2026
4a95072
fix(db): abort declarative generate on unreadable overwrite dir to ma…
Coly010 Jun 17, 2026
f26da1c
fix(db): cache linked query ref before SQL-resolution failures to mat…
Coly010 Jun 17, 2026
552172e
fix(db): cache linked dump ref before resolver failures to match Go P…
Coly010 Jun 17, 2026
e8a3ffd
fix(db): surface project-ref read failures instead of treating them a…
Coly010 Jun 17, 2026
43b636d
fix(db): report query -f as file in telemetry to match Go flags.Visit…
Coly010 Jun 17, 2026
5409d69
fix(db): print dump post-run message on --dry-run --file to match Go …
Coly010 Jun 17, 2026
2b1e834
fix(db): cache linked ref discovered by smart generate to match Go Po…
Coly010 Jun 17, 2026
9d811b0
fix(db): cache linked ref during declarative sync bootstrap to match …
Coly010 Jun 17, 2026
842dfd6
chore(db): apply oxfmt formatting to dump/generate test files and SID…
Coly010 Jun 17, 2026
6eb92e4
fix(db): validate linked query access token via credentials.getAccess…
Coly010 Jun 17, 2026
6b2dd35
fix(db): report declarative generate/sync shorthands in telemetry to …
Coly010 Jun 17, 2026
a614aec
chore(db): apply oxfmt to declarative generate/sync telemetry test ca…
Coly010 Jun 17, 2026
02327f6
fix(db): use hard loadProjectRef for linked query so ref read errors …
Coly010 Jun 17, 2026
aa11d57
fix(db): parse api.auto_expose_new_tables with Go bool + env override…
Coly010 Jun 17, 2026
f8df2b0
fix(db): attach IPv6 transaction-pooler suggestion to failed linked d…
Coly010 Jun 17, 2026
5f8387c
fix(db): tolerate unreadable migrations/ref in smart generate probes …
Coly010 Jun 17, 2026
97de71e
fix(db): tolerate unreadable migrations/ref in sync bootstrap probes …
Coly010 Jun 17, 2026
7df3a4c
fix(db): use hard loadProjectRef in linked resolver so ref read error…
Coly010 Jun 17, 2026
320edef
fix(db): warm linked generate catalog with the remote-merged config t…
Coly010 Jun 17, 2026
04dfb95
fix(db): validate function slugs on config load to match Go ValidateF…
Coly010 Jun 17, 2026
8be7d81
Merge remote-tracking branch 'origin/develop' into cli/port-db-dump-q…
Coly010 Jun 18, 2026
c67b17b
docs(db): correct dump SIDE_EFFECTS pooler-fallback note to match shi…
Coly010 Jun 18, 2026
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
38 changes: 38 additions & 0 deletions apps/cli-go/cmd/pgdelta_catalog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cmd

import (
"fmt"

"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/supabase/cli/internal/db/declarative"
)

// pgdeltaCatalogMode selects which catalog the hidden seam command produces.
var pgdeltaCatalogMode string

// dbDeclarativeCatalogCmd is a hidden seam used by the native-TypeScript
// declarative commands to provision a shadow-database platform baseline (and,
// for migrations/declarative modes, apply migrations / declarative files) and
// export the resulting pg-delta catalog. It prints the catalog file path to
// stdout. Inherits the declarative group's PersistentPreRunE (the
// experimental/pg-delta gate + config load), so callers must pass
// --experimental or enable [experimental.pgdelta].
var dbDeclarativeCatalogCmd = &cobra.Command{
Use: "__catalog",
Hidden: true,
Short: "Internal: export a pg-delta catalog for the native declarative commands",
RunE: func(cmd *cobra.Command, args []string) error {
ref, err := declarative.ExportModeCatalog(cmd.Context(), pgdeltaCatalogMode, declarativeNoCache, afero.NewOsFs())
if err != nil {
return err
}
fmt.Println(ref)
return nil
},
}

func init() {
dbDeclarativeCatalogCmd.Flags().StringVar(&pgdeltaCatalogMode, "mode", "", "Catalog mode: baseline, migrations, or declarative.")
dbDeclarativeCmd.AddCommand(dbDeclarativeCatalogCmd)
}
41 changes: 41 additions & 0 deletions apps/cli-go/internal/db/declarative/seam.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package declarative

import (
"context"

"github.com/go-errors/errors"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
)

// ExportModeCatalog produces (and caches under supabase/.temp/pgdelta/) the
// pg-delta catalog for the given mode and returns its on-disk path.
//
// It is the seam consumed by the native-TypeScript `db schema declarative`
// commands: they own orchestration, the pg-delta diff/export, file writes, and
// prompts, but delegate the shadow-database platform-baseline provisioning
// (start.SetupDatabase, which runs the auth/storage/realtime service migrations)
// to this Go path, which is not yet ported.
//
// - "baseline": platform baseline only (no user migrations) — the generate source.
// - "migrations": platform baseline + local migrations applied — the sync source.
// - "declarative": platform baseline + declarative files applied — the sync target.
func ExportModeCatalog(ctx context.Context, mode string, noCache bool, fsys afero.Fs, options ...func(*pgx.ConnConfig)) (string, error) {
switch mode {
case "migrations":
return getMigrationsCatalogRef(ctx, noCache, fsys, "local", options...)
case "declarative":
return getDeclarativeCatalogRef(ctx, noCache, fsys, options...)
case "baseline":
ref, err := getGenerateBaselineCatalogRef(ctx, noCache, fsys, options...)
if err != nil {
return "", err
}
if ref.shadow != nil {
ref.shadow.cleanup()
}
return ref.ref, nil
default:
return "", errors.Errorf("unknown catalog mode: %s", mode)
}
}
8 changes: 4 additions & 4 deletions apps/cli/docs/go-cli-porting-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,13 @@ Legend:
| `test new` | `ported` | [`../src/legacy/commands/test/new/new.command.ts`](../src/legacy/commands/test/new/new.command.ts) |
| `seed buckets` | `wrapped` | [`../src/legacy/commands/seed/buckets/buckets.command.ts`](../src/legacy/commands/seed/buckets/buckets.command.ts) |
| `db diff` | `wrapped` | [`../src/legacy/commands/db/diff/diff.command.ts`](../src/legacy/commands/db/diff/diff.command.ts) |
| `db dump` | `wrapped` | [`../src/legacy/commands/db/dump/dump.command.ts`](../src/legacy/commands/db/dump/dump.command.ts) |
| `db dump` | `ported` | [`../src/legacy/commands/db/dump/dump.command.ts`](../src/legacy/commands/db/dump/dump.command.ts) |
| `db push` | `wrapped` | [`../src/legacy/commands/db/push/push.command.ts`](../src/legacy/commands/db/push/push.command.ts) |
| `db pull` | `wrapped` | [`../src/legacy/commands/db/pull/pull.command.ts`](../src/legacy/commands/db/pull/pull.command.ts) — includes `--declarative` (deprecated alias `--use-pg-delta`) and `--diff-engine` (migra\|pg-delta, mutually exclusive with `--declarative`) |
| `db reset` | `wrapped` | [`../src/legacy/commands/db/reset/reset.command.ts`](../src/legacy/commands/db/reset/reset.command.ts) |
| `db lint` | `ported` | [`../src/legacy/commands/db/lint/lint.command.ts`](../src/legacy/commands/db/lint/lint.command.ts) |
| `db start` | `wrapped` | [`../src/legacy/commands/db/start/start.command.ts`](../src/legacy/commands/db/start/start.command.ts) |
| `db query` | `wrapped` | [`../src/legacy/commands/db/query/query.command.ts`](../src/legacy/commands/db/query/query.command.ts) |
| `db query` | `ported` | [`../src/legacy/commands/db/query/query.command.ts`](../src/legacy/commands/db/query/query.command.ts) |
| `db advisors` | `ported` | [`../src/legacy/commands/db/advisors/advisors.command.ts`](../src/legacy/commands/db/advisors/advisors.command.ts) |
| `db test` | `wrapped` | [`../src/legacy/commands/db/test/test.command.ts`](../src/legacy/commands/db/test/test.command.ts) |
| `db branch create` | `wrapped` | [`../src/legacy/commands/db/branch/create/create.command.ts`](../src/legacy/commands/db/branch/create/create.command.ts) |
Expand All @@ -314,5 +314,5 @@ Legend:
| `db branch switch` | `wrapped` | [`../src/legacy/commands/db/branch/switch/switch.command.ts`](../src/legacy/commands/db/branch/switch/switch.command.ts) |
| `db remote changes` | `wrapped` | [`../src/legacy/commands/db/remote/changes/changes.command.ts`](../src/legacy/commands/db/remote/changes/changes.command.ts) |
| `db remote commit` | `wrapped` | [`../src/legacy/commands/db/remote/commit/commit.command.ts`](../src/legacy/commands/db/remote/commit/commit.command.ts) |
| `db schema declarative sync` | `wrapped` | [`../src/legacy/commands/db/schema/declarative/sync/sync.command.ts`](../src/legacy/commands/db/schema/declarative/sync/sync.command.ts) |
| `db schema declarative generate` | `wrapped` | [`../src/legacy/commands/db/schema/declarative/generate/generate.command.ts`](../src/legacy/commands/db/schema/declarative/generate/generate.command.ts) |
| `db schema declarative sync` | `ported` | [`../src/legacy/commands/db/schema/declarative/sync/sync.command.ts`](../src/legacy/commands/db/schema/declarative/sync/sync.command.ts) |
| `db schema declarative generate` | `ported` | [`../src/legacy/commands/db/schema/declarative/generate/generate.command.ts`](../src/legacy/commands/db/schema/declarative/generate/generate.command.ts) |
17 changes: 13 additions & 4 deletions apps/cli/src/legacy/auth/legacy-platform-api-factory.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import type {
LegacyPlatformAuthRequiredError,
} from "./legacy-errors.ts";

/**
* The error `make` can fail with when it lazily resolves the access token and
* constructs the typed client. Surfaces only when a command branch actually
* reaches a Management API call — never at layer build — so consumers that route
* through the lazy factory (e.g. the `--linked` db-config resolver) must include
* it in their own effect error channel rather than a layer-build error channel.
*/
export type LegacyPlatformApiFactoryError =
| LegacyInvalidAccessTokenError
| LegacyPlatformAuthRequiredError
| SupabaseApiConfigError;

/**
* Lazy accessor for the typed Management API client.
*
Expand All @@ -14,10 +26,7 @@ import type {
* branch actually reaches a Management API call.
*/
export interface LegacyPlatformApiFactoryShape {
readonly make: Effect.Effect<
ApiClient,
LegacyInvalidAccessTokenError | LegacyPlatformAuthRequiredError | SupabaseApiConfigError
>;
readonly make: Effect.Effect<ApiClient, LegacyPlatformApiFactoryError>;
}

export class LegacyPlatformApiFactory extends Context.Service<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import { tmpdir } from "node:os";
import path from "node:path";
import { vi } from "vitest";

import { LegacyDebugFlag } from "../../shared/legacy/global-flags.ts";
import { LegacyDebugFlag, LegacyDnsResolverFlag } from "../../shared/legacy/global-flags.ts";
import { Analytics } from "../../shared/telemetry/analytics.service.ts";
import { TelemetryRuntime } from "../../shared/telemetry/runtime.service.ts";
import { makeTelemetryIdentity } from "../../shared/telemetry/identity.ts";
import { LegacyCliConfig } from "../config/legacy-cli-config.service.ts";
import { legacyDebugLoggerLayer } from "../shared/legacy-debug-logger.layer.ts";
import { legacyIdentityStitchLayer } from "../shared/legacy-identity-stitch.ts";
import { LegacyCredentials } from "./legacy-credentials.service.ts";
import { legacyPlatformApiFactoryLayer } from "./legacy-platform-api-factory.layer.ts";
import { LegacyPlatformApiFactory } from "./legacy-platform-api-factory.service.ts";
import { legacyPlatformApiLayer } from "./legacy-platform-api.layer.ts";
import { LegacyPlatformApi } from "./legacy-platform-api.service.ts";

Expand Down Expand Up @@ -193,6 +195,8 @@ function withBaseDeps(
Layer.provide(identityStitch),
Layer.provide(legacyDebugLoggerLayer),
Layer.provide(Layer.succeed(LegacyDebugFlag, opts.debug ?? false)),
// The lazy platform-API factory's DoH fetch layer reads the DNS-resolver flag.
Layer.provide(Layer.succeed(LegacyDnsResolverFlag, "native")),
);
}

Expand Down Expand Up @@ -522,3 +526,59 @@ describe("legacyPlatformApiLayer", () => {
}).pipe(Effect.provide(layer));
});
});

// The lazy factory underpins the `--linked` db-config resolver's auth-free
// `--password` path (CLI port of Go's `NewDbConfigWithPassword`, which only calls
// `GetSupabase` — and thus loads a token — when no password is supplied). Building
// the factory must therefore resolve NO token; the friendly auth error must still
// surface when a command branch actually reaches `make` (e.g. minting a temp role).
describe("legacyPlatformApiFactoryLayer (lazy token)", () => {
it.effect("builds without resolving an access token even when none is configured", () => {
const layer = legacyPlatformApiFactoryLayer.pipe(
Layer.provide(mockCliConfig({})),
Layer.provide(mockCredentials(Option.none())),
withBaseDeps(),
);
// The eager `legacyPlatformApiLayer` would fail to build here; obtaining the
// factory service without touching `make` must succeed — this is exactly the
// `--linked --password` path, which never mints a temp role.
return Effect.gen(function* () {
const factory = yield* LegacyPlatformApiFactory;
expect(typeof factory.make).toBe("object");
}).pipe(Effect.provide(layer));
});

it.effect("make fails with LegacyPlatformAuthRequiredError when no token is configured", () => {
const layer = legacyPlatformApiFactoryLayer.pipe(
Layer.provide(mockCliConfig({})),
Layer.provide(mockCredentials(Option.none())),
withBaseDeps(),
);
return Effect.gen(function* () {
const factory = yield* LegacyPlatformApiFactory;
const exit = yield* Effect.exit(factory.make);
expect(Exit.isFailure(exit)).toBe(true);
if (Exit.isFailure(exit)) {
const errorJson = JSON.stringify(exit.cause);
expect(errorJson).toContain("LegacyPlatformAuthRequiredError");
expect(errorJson).toContain("Access token not provided");
}
}).pipe(Effect.provide(layer));
});

it.effect("make resolves a single cached client when a token is configured", () => {
const layer = legacyPlatformApiFactoryLayer.pipe(
Layer.provide(mockCliConfig({ accessToken: VALID_TOKEN })),
Layer.provide(mockCredentials(Option.none())),
withBaseDeps(),
);
return Effect.gen(function* () {
const factory = yield* LegacyPlatformApiFactory;
const first = yield* factory.make;
const second = yield* factory.make;
// `Effect.cached` guarantees the token is resolved once and the same client
// instance is reused across repeated `make` calls within one command run.
expect(first).toBe(second);
}).pipe(Effect.provide(layer));
});
});
13 changes: 7 additions & 6 deletions apps/cli/src/legacy/cli/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,14 @@ export const legacyRoot = Command.make("supabase").pipe(
if (createTicket) globalArgs.push("--create-ticket");
if (agent !== "auto") globalArgs.push("--agent", agent);

// Go's `-o {json,yaml,toml,env}` selects a machine encoder the handler
// writes via `output.raw`. Keep the text layer (so errors still render
// as red text on stderr, matching Go), but suppress its progress spinner
// — otherwise clack writes ANSI to stdout and corrupts the payload
// (CLI-1546). `-o pretty` / no `-o` keep the normal text/json layers.
// Go's `-o {json,yaml,toml,env,csv}` selects a machine encoder the
// handler writes via `output.raw`. Keep the text layer (so errors still
// render as red text on stderr, matching Go), but suppress its progress
// spinner — otherwise clack writes ANSI to stdout and corrupts the
// payload (CLI-1546). `-o pretty` / `-o table` (`db query`'s human
// default) / no `-o` keep the normal text/json layers.
const goFmt = Option.getOrUndefined(goOutput);
const isGoMachineFormat = goFmt !== undefined && goFmt !== "pretty";
const isGoMachineFormat = goFmt !== undefined && goFmt !== "pretty" && goFmt !== "table";
const outputLayer = isGoMachineFormat
? legacyQuietProgressTextOutputLayer
: outputLayerFor(outputFormat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function mockResolver(opts: { ipv6Error?: boolean } = {}) {
isLocal: flags.connType !== "linked",
} satisfies LegacyResolvedDbConfig;
}),
resolvePoolerFallback: () => Effect.succeed(Option.none()),
});
return {
layer,
Expand All @@ -106,6 +107,7 @@ function mockConnection(opts: {
Effect.succeed({
extensionExists: () => Effect.succeed(false),
copyToCsv: () => Effect.succeed(new Uint8Array()),
queryRaw: () => Effect.succeed({ fields: [], rows: [], commandTag: "" }),
exec: (sql: string) =>
Effect.suspend(() => {
execs.push(sql);
Expand Down
Loading
Loading