Skip to content

Add the traceroot sql CLI command (API client, CSV/table/JSON/file output) #27

Description

@dark-sorceror

Summary

Deliver the primary CLI surface — traceroot sql "<query>" — plus the API-client methods and CSV renderer it composes.

Context

  • Lives in the TypeScript CLI repo (traceroot-cli): Commander.js + native fetch + Vitest. Existing client (src/api/client.ts) does bearer auth + key scrubbing; extend with POST. No CSV lib — hand-roll (RFC-4180).
  • Analytical export framing: results are metric/dimension columns only; blobs are excluded.
  • Can develop against the frozen public SQL API contract before backend merge.

Implementation

  • src/api/client.ts — types SqlColumn/SqlQueryRequest/SqlQueryResponse/SqlSchemaResponse; sqlQuery(body) (POST /api/v1/public/sql) + sqlSchema() (GET) reusing header construction + key scrubbing (generalize request<T> to method+body).
  • src/render/csv.tsrenderCsv(headers, rows): RFC-4180 quoting for ,/"/newline; null/undefined → empty; objects JSON-stringified; trailing \n.
  • src/commands/sql.tsregisterSql(program): create the sql group, register the schema subcommand before the default [query] action (so sql schema resolves as a subcommand).
  • src/commands/sql/query.tsregisterSqlQuery + runSqlQuery: optional [query], -f/--file, --csv, --output <file>, --max-rows <n> (forwarded to the request body so the truncation hint is honest), reuse global --json. Exactly one of positional/--file required (else error); --json+--csv is an error. Output: table (default) / JSON line / CSV; --output writes any format to a file. On truncated in table/CSV mode, stderr warning (mentions --max-rows/LIMIT); JSON mode relies on the truncated field. Wrap file read/write errors as a readable CliError. Error/exit handling follows the CLI's existing conventions (the established reportError/CliError path) — do not introduce a new numeric exit-code taxonomy unless the CLI already defines one. Surface failures as readable messages: validation rejections print the server detail; resource-cap messages add a LIMIT/time-filter hint.
  • Register the group in src/commands/index.ts.

Test plan

  • tests/api/sql-client.test.ts: sqlQuery POSTs to the right URL with bearer auth; key scrubbing preserved; params serialized into the body.
  • tests/render/csv.test.ts: header+rows; comma/quote/newline escaping; null/undefined → empty.
  • tests/commands/sql-query.test.ts (via runSqlQuery + fake client + StringSink): default table; --json line; --csv; --json+--csv rejects; positional+--file and neither reject; --output writes file; truncated warns on stderr (table/CSV) but not JSON. One runCli surface test (unknown flag is rejected per the CLI's normal error handling).

Acceptance criteria

  • traceroot sql "<query>" prints a table by default; --json one JSON line; --csv RFC-4180; --output <file> writes any format; -f/--file reads the query; --max-rows <n> forwarded.
  • Exactly one of positional/--file required; --json+--csv is an error; truncation warns on stderr (table/CSV), self-describing in JSON.
  • Errors and exits follow the CLI's existing conventions (no new exit-code taxonomy); file and validation errors are surfaced as readable messages; resource-cap rejections include a LIMIT/time-filter hint.
  • sqlQuery/sqlSchema POST/GET with bearer auth; key scrubbing preserved; renderCsv handles commas/quotes/newlines/null.
  • All new Vitest tests pass; npm run build clean; no regressions.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions