Skip to content

feat(cli): port snippets commands to native TypeScript#5381

Merged
Coly010 merged 4 commits into
developfrom
cli/port-snippets-commands
May 29, 2026
Merged

feat(cli): port snippets commands to native TypeScript#5381
Coly010 merged 4 commits into
developfrom
cli/port-snippets-commands

Conversation

@Coly010
Copy link
Copy Markdown
Contributor

@Coly010 Coly010 commented May 28, 2026

Summary

Replaces the Phase 0 Go-binary proxies for supabase snippets list and supabase snippets download with native Effect handlers. Mirrors Go's output bytes, error messages, exit codes, and lifecycle (linked-project cache + telemetry flush on every exit). Adds TS-only --output-format json|stream-json events on top, exposing the full Management-API payload to scripted callers.

Changes

  • snippets list: native handler against GET /v1/snippets?project_ref=<ref> with Glamour ASCII table, --output env rejection after ref resolution (Go-bytes), Go-compatible JSON/YAML/TOML encoders, nullForEmptyArrays: ["data"] for empty-list parity
  • snippets download: native handler against GET /v1/snippets/{id} with UUID pre-validation reproducing google/uuid v1.6.0's two-flavor error surface (invalid UUID length: N / invalid UUID format); raw SQL + trailing \n in text mode; full response payload under --output-format json
  • Lifecycle parity: both handlers wrap in nested Effect.gen blocks so telemetryState.flush (Go Execute) fires on every exit and linkedProjectCache.cache(ref) (Go PersistentPostRun) fires for every path where the ref resolved — including --output env and invalid-UUID early-exits
  • Hoist: formatBackupTimestamplegacy/shared/legacy-timestamp.format.ts::formatLegacyTimestamp (snippets is the second consumer, per apps/cli/CLAUDE.md "Hoist Before You Duplicate")
  • Test helpers: LegacyRecordedRequest now captures urlParams + urlWithParams so tests can assert on GET query parameters
  • Docs: SIDE_EFFECTS.md rewritten for both commands; docs/go-cli-porting-status.md flips both from wrappedported

Go parity contract

Surface Verified against
--output env rejection apps/cli-go/internal/utils/output.go:41 (byte-exact --output env flag is not supported)
UUID error prefix apps/cli-go/internal/snippets/download/download.go:17 + google/uuid v1.6.0
Table columns / pipe escape apps/cli-go/internal/snippets/list/list.go:27-41
JSON "data": null for empty list list_test.go::encodes json output fixture
download ignores --output download.go:25 (fmt.Println unconditional)
Telemetry safe-flag policy apps/cli-go/cmd/snippets.go has no markFlagTelemetrySafe--project-ref value is redacted

Fixes CLI-1299

@Coly010 Coly010 requested a review from a team as a code owner May 28, 2026 15:10
Coly010 added 2 commits May 28, 2026 16:15
Replaces the Phase 0 Go-binary proxies for `supabase snippets list` and
`supabase snippets download` with native Effect handlers. Mirrors Go's
output bytes, error messages, exit codes, and PersistentPostRun/Execute
lifecycle (linked-project cache + telemetry flush on every exit). Adds
TS-only `--output-format json|stream-json` events on top, exposing the
full Management-API payload to scripted callers.

Hoists `formatBackupTimestamp` to `legacy/shared/legacy-timestamp.format.ts`
as `formatLegacyTimestamp` (second consumer triggered the hoist rule).
Adds `urlParams` + `urlWithParams` to `LegacyRecordedRequest` so tests
can assert on GET-style query parameters.

Fixes CLI-1299
…und-trip)

The orgs port (#5379) documented an important parity rule: Go's
`strings.ReplaceAll(value, "|", "\\|")` is a markdown-intermediate escape
that Glamour decodes back to literal `|` in the rendered ASCII bytes.
`renderGlamourTable` bypasses the markdown round-trip, so passing
pre-escaped values produces `\|` in stdout where Go produces `|` — a
byte-level parity divergence for any snippet name, visibility, or owner
username containing a pipe.

Fix: drop the `escapePipe` helper, pass raw values to renderGlamourTable.
Updated unit + integration tests to assert literal `|` preservation
(matching the pattern orgs.format.unit.test.ts uses).

Also adopts the `yield* new ErrorClass(...)` shorthand from orgs handlers
for tagged-error short-circuits.
@Coly010 Coly010 force-pushed the cli/port-snippets-commands branch from 4a65096 to fb4dee3 Compare May 29, 2026 08:27
@Coly010 Coly010 self-assigned this May 29, 2026
…scription

The cli-e2e suite caught two failures:

1. `snippets:download > prints SQL content to stdout` exited 1 with
   `SchemaError: Missing key at ["description"]`. The generated
   `V1GetASnippetOutput` schema declares `description` as
   `Union[String, Null]` (present-but-nullable), but real `/v1/snippets/{id}`
   responses omit the field entirely. Strict decode through `LegacyPlatformApi`
   therefore fails on every realistic payload — only the synthetic Go unit-test
   fixture (which uses a nil slice) round-trips.

2. `snippets:list --output json` returned `{"data": null}` while the test
   expects `Array.isArray(parsed.data)` to be true. The `nullForEmptyArrays`
   hack was modelling a Go unit-fixture (nil slice → null) rather than the
   actual API behaviour (empty array → []). Go's `encoding/json` preserves
   nil-vs-empty faithfully; we did not.

Fix: drop both handlers to raw `HttpClient.HttpClient` (same workaround as
`legacy-linked-project-cache.layer.ts` and `legacySuggestUpgrade`), and
remove `nullForEmptyArrays: ["data"]`. The raw bypass lets us echo whatever
the API actually returned — preserving `[]` when the API sends `[]`, and
tolerating responses without `description`.

Adds tolerant accessors (`readString`, `asRecord`, `parseSnippetsResponse`,
`toSnippetRow`, `readSql`) to extract only the fields the renderer needs.
Keeps error mapping byte-exact (`failed to list snippets`, `unexpected list
snippets status N: …`, equivalents for download), spinner / output-mode
dispatch, and the nested `Effect.ensuring` lifecycle blocks for telemetry
and linked-project cache parity.

Updated the unit test that asserted `{"data": null}` for empty input — the
realistic round-trip is `{"data": []}` now. All 36 snippets in-process
tests pass; the 17 snippets e2e tests pass locally.
@Coly010 Coly010 merged commit 5072003 into develop May 29, 2026
9 checks passed
@Coly010 Coly010 deleted the cli/port-snippets-commands branch May 29, 2026 10:49
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