feat(cli): port snippets commands to native TypeScript#5381
Merged
Conversation
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.
4a65096 to
fb4dee3
Compare
…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.
jgoux
approved these changes
May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the Phase 0 Go-binary proxies for
supabase snippets listandsupabase snippets downloadwith 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-jsonevents on top, exposing the full Management-API payload to scripted callers.Changes
snippets list: native handler againstGET /v1/snippets?project_ref=<ref>with Glamour ASCII table,--output envrejection after ref resolution (Go-bytes), Go-compatible JSON/YAML/TOML encoders,nullForEmptyArrays: ["data"]for empty-list paritysnippets download: native handler againstGET /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\nin text mode; full response payload under--output-format jsonEffect.genblocks sotelemetryState.flush(GoExecute) fires on every exit andlinkedProjectCache.cache(ref)(GoPersistentPostRun) fires for every path where the ref resolved — including--output envand invalid-UUID early-exitsformatBackupTimestamp→legacy/shared/legacy-timestamp.format.ts::formatLegacyTimestamp(snippets is the second consumer, perapps/cli/CLAUDE.md"Hoist Before You Duplicate")LegacyRecordedRequestnow capturesurlParams+urlWithParamsso tests can assert on GET query parametersSIDE_EFFECTS.mdrewritten for both commands;docs/go-cli-porting-status.mdflips both fromwrapped→portedGo parity contract
--output envrejectionapps/cli-go/internal/utils/output.go:41(byte-exact--output env flag is not supported)apps/cli-go/internal/snippets/download/download.go:17+ google/uuid v1.6.0apps/cli-go/internal/snippets/list/list.go:27-41"data": nullfor empty listlist_test.go::encodes json outputfixturedownloadignores--outputdownload.go:25(fmt.Printlnunconditional)apps/cli-go/cmd/snippets.gohas nomarkFlagTelemetrySafe—--project-refvalue is redactedFixes CLI-1299