From 940a6a9eda671a3f0798e6182f98f2de2e737f5d Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Thu, 4 Jun 2026 11:59:01 +0100 Subject: [PATCH 1/2] feat(cli): port bootstrap command to native TypeScript Replaces the Phase-0 Go proxy for `supabase bootstrap` with a native TypeScript implementation in the legacy shell. The command orchestrates: workdir resolve/prompt -> template list/download -> blank init -> ensure-login -> projects create -> api-keys (backoff) -> link services -> health poll (backoff) -> write .env -> db push -> start suggestion. Every step is native except the migration push, which is delegated to the bundled Go binary via LegacyGoProxy as a documented interim until `db push` is natively ported (LegacyGoProxy.exec exits on non-zero rather than failing, so its push backoff is not reproducible from the proxy). Per the "hoist before you duplicate" policy, shared orchestration cores are extracted from the already-ported login/create/api-keys/link handlers and those handlers refactored to delegate: - legacy-ensure-login (browser login + post-login telemetry) - legacy-project-create-core - legacy-get-api-keys - legacy-link-services-core - legacy-tenant-keys (legacyExtractServiceKeys) - login api/crypto layers moved to legacy/shared so bootstrap composes them without a cross-command import Go-parity notes: - bootstrap fires no cli_project_linked event: Go calls link.LinkServices (services only), not link.Run, so it skips the project-linked telemetry, status check, and linked-project.json temp write. - api-keys are fetched without `reveal` (Go's RunGetApiKeys uses empty params). - workdir / db-password env vars are read prefixed (SUPABASE_WORKDIR, SUPABASE_DB_PASSWORD) to match Go's viper SetEnvPrefix("SUPABASE"). - "Using workdir" prints only when the resolved workdir differs from the cwd. Template download validates entries stay within the target directory, and GitHub/health error bodies are sanitized before surfacing. --- apps/cli/docs/go-cli-porting-status.md | 8 +- .../legacy/commands/bootstrap/SIDE_EFFECTS.md | 132 +++-- .../commands/bootstrap/bootstrap.command.ts | 10 +- .../commands/bootstrap/bootstrap.dotenv.ts | 174 +++++++ .../bootstrap/bootstrap.dotenv.unit.test.ts | 121 +++++ .../commands/bootstrap/bootstrap.errors.ts | 54 +++ .../commands/bootstrap/bootstrap.handler.ts | 294 +++++++++++- .../bootstrap/bootstrap.integration.test.ts | 449 ++++++++++++++++++ .../commands/bootstrap/bootstrap.layers.ts | 55 +++ .../commands/bootstrap/bootstrap.pgconfig.ts | 74 +++ .../bootstrap/bootstrap.pgconfig.unit.test.ts | 68 +++ .../commands/bootstrap/bootstrap.suggest.ts | 34 ++ .../bootstrap/bootstrap.suggest.unit.test.ts | 36 ++ .../commands/bootstrap/bootstrap.templates.ts | 229 +++++++++ .../src/legacy/commands/link/link.handler.ts | 121 +---- .../legacy/commands/login/login.handler.ts | 137 +----- .../src/legacy/commands/login/login.layers.ts | 4 +- .../projects/api-keys/api-keys.handler.ts | 18 +- .../projects/create/create.handler.ts | 148 +----- apps/cli/src/legacy/shared/legacy-colors.ts | 22 + .../src/legacy/shared/legacy-ensure-login.ts | 181 +++++++ .../src/legacy/shared/legacy-get-api-keys.ts | 33 ++ .../shared/legacy-link-services-core.ts | 126 +++++ .../legacy-login-api.layer.ts} | 9 +- .../legacy-login-crypto.layer.ts} | 7 +- .../shared/legacy-project-create-core.ts | 167 +++++++ .../src/legacy/shared/legacy-tenant-keys.ts | 43 ++ 27 files changed, 2301 insertions(+), 453 deletions(-) create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.dotenv.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.dotenv.unit.test.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.errors.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.integration.test.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.layers.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.pgconfig.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.pgconfig.unit.test.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.suggest.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.suggest.unit.test.ts create mode 100644 apps/cli/src/legacy/commands/bootstrap/bootstrap.templates.ts create mode 100644 apps/cli/src/legacy/shared/legacy-colors.ts create mode 100644 apps/cli/src/legacy/shared/legacy-ensure-login.ts create mode 100644 apps/cli/src/legacy/shared/legacy-get-api-keys.ts create mode 100644 apps/cli/src/legacy/shared/legacy-link-services-core.ts rename apps/cli/src/legacy/{commands/login/login-api.layer.ts => shared/legacy-login-api.layer.ts} (92%) rename apps/cli/src/legacy/{commands/login/login-crypto.layer.ts => shared/legacy-login-crypto.layer.ts} (93%) create mode 100644 apps/cli/src/legacy/shared/legacy-project-create-core.ts create mode 100644 apps/cli/src/legacy/shared/legacy-tenant-keys.ts diff --git a/apps/cli/docs/go-cli-porting-status.md b/apps/cli/docs/go-cli-porting-status.md index ff70e62590..1abb8ab283 100644 --- a/apps/cli/docs/go-cli-porting-status.md +++ b/apps/cli/docs/go-cli-porting-status.md @@ -57,9 +57,9 @@ These commands exist in the TS CLI today but have no direct top-level equivalent ## Quick Start -| Old command | TS status | TS command path or `missing` | Missing flags/params | Extra TS flags/params | Notes | -| ----------- | --------- | ---------------------------- | -------------------- | --------------------- | ------------------------------------------- | -| `bootstrap` | `missing` | `missing` | `n/a` | `n/a` | No TS command yet. Wrapped in legacy shell. | +| Old command | TS status | TS command path or `missing` | Missing flags/params | Extra TS flags/params | Notes | +| ----------- | --------- | ---------------------------- | -------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `bootstrap` | `missing` | `missing` | `n/a` | `n/a` | No `next/` command yet. Ported to native TS in the legacy shell; the migration-push sub-step is delegated to the Go binary as a documented interim until `db push` is natively ported. | ## Project / Stack Lifecycle @@ -265,7 +265,7 @@ Legend: | `logout` | `ported` | [`../src/legacy/commands/logout/logout.command.ts`](../src/legacy/commands/logout/logout.command.ts) | | `link` | `ported` | [`../src/legacy/commands/link/link.command.ts`](../src/legacy/commands/link/link.command.ts) | | `unlink` | `ported` | [`../src/legacy/commands/unlink/unlink.command.ts`](../src/legacy/commands/unlink/unlink.command.ts) | -| `bootstrap` | `wrapped` | [`../src/legacy/commands/bootstrap/bootstrap.command.ts`](../src/legacy/commands/bootstrap/bootstrap.command.ts) | +| `bootstrap` | `ported` | [`../src/legacy/commands/bootstrap/bootstrap.command.ts`](../src/legacy/commands/bootstrap/bootstrap.command.ts) (native; `db push` step delegated to the Go binary — interim) | | `init` | `ported` | [`../src/legacy/commands/init/init.command.ts`](../src/legacy/commands/init/init.command.ts) | | `services` | `wrapped` | [`../src/legacy/commands/services/services.command.ts`](../src/legacy/commands/services/services.command.ts) | | `start` | `wrapped` | [`../src/legacy/commands/start/start.command.ts`](../src/legacy/commands/start/start.command.ts) | diff --git a/apps/cli/src/legacy/commands/bootstrap/SIDE_EFFECTS.md b/apps/cli/src/legacy/commands/bootstrap/SIDE_EFFECTS.md index 720d4096b6..c43ac9d168 100644 --- a/apps/cli/src/legacy/commands/bootstrap/SIDE_EFFECTS.md +++ b/apps/cli/src/legacy/commands/bootstrap/SIDE_EFFECTS.md @@ -1,71 +1,115 @@ # `supabase bootstrap [template]` +`bootstrap` is a meta-orchestrator: it chains a workdir prompt → template fetch/download → +blank `init` → ensure-login → `projects create` → `projects api-keys` → `link` services → +health poll → write `.env` → `db push` → start suggestion. Every step is native TypeScript +**except** the migration push, which is delegated to the bundled Go binary (interim — see Notes). + ## Files Read -| Path | Format | When | -| -------------------------- | ------------------------- | ---------------------------------------------------------- | -| `~/.supabase/access-token` | plain text (token string) | when `SUPABASE_ACCESS_TOKEN` unset and keyring unavailable | +| Path | Format | When | +| -------------------------------------- | ---------- | ----------------------------------------------------------- | +| `~/.supabase/access-token` | plain text | ensure-login token miss (env unset and keyring unavailable) | +| `/.env.example` | dotenv | optional; merged into the generated `.env` | +| `/supabase/.temp/project-ref` | plain text | read by the delegated `db push` subprocess (post-`chdir`) | ## Files Written -| Path | Format | When | -| -------------------------------- | ------ | ------------------------------------------------------------- | -| `/supabase/config.toml` | TOML | always on success; created from selected template | -| `/.env` | env | always on success; populated with API keys and project config | -| `/