Update to latest API#2
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the CLI to accommodate a flatter API response structure by removing response envelopes in tests and the API key validation logic. It also renames pagination parameters from limit/offset to page/size and introduces a new api command for raw API access via OpenAPI specifications. Additionally, error handling has been enhanced to provide more detailed feedback. Feedback was provided to optimize the request forwarding utility by streaming the request body instead of buffering it in memory to avoid potential performance and memory issues.
| if (req.method !== 'GET' && req.method !== 'HEAD') { | ||
| init.body = await req.text() | ||
| } |
There was a problem hiding this comment.
Buffering the entire request body into memory as a string using req.text() is inefficient for large payloads and can lead to memory exhaustion or issues with binary data. Since this is a proxy-like forwarding function, it is better to pass the request body stream directly to fetch. Note that in Node.js environments, when passing a stream as a body to fetch, you must also set the duplex property to 'half'.
| if (req.method !== 'GET' && req.method !== 'HEAD') { | |
| init.body = await req.text() | |
| } | |
| if (req.body) { | |
| init.body = req.body | |
| // @ts-ignore - duplex is required for streaming bodies in Node.js fetch | |
| init.duplex = 'half' | |
| } |
Re-vendor openapi.json from formono and update list-endpoint tests to
consume the new PaginatedResponse<T> envelope ({ data, total, page,
size, has_more }). Charts list now reads res.data (was res.charts);
contracts list now reads res.data + res.deploy (was res.contracts +
top-level deployAt/deployDiff). New getContract op surfaces
automatically via `formo api getContract`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the auto-generated passthrough subcommands and the vendored openapi.json (~215KB). The hand-written commands (alerts, boards, charts, contracts, segments, profiles, query, import) cover the human-facing surface; raw access wasn't paying its weight in bundle size and discoverability cost. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 11 failing integration tests were all hitting api.formo.so and returning 401 — the configured TEST_TOKEN is unauthorized. Probe the API once via /api/validate-api-key at suite startup; if the probe returns 401/403 (or the host is unreachable), every test that needs the live API skips with a clear stderr message instead of producing a wall of identical 401 stack traces. Action item for CI: rotate TEST_TOKEN to a key with the required scopes (alerts:read, boards:read, charts:read, contracts:read, segments:read, profiles:read, query:read). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire the three new /v0/profiles/{address}/(properties|labels)
endpoints into the profiles subcommand surface:
- profiles set-properties <address> --properties '<json>' → PUT
identity properties (display_name, twitter, ens, etc.). Only the
22 allowed keys are accepted server-side.
- profiles add-label <address> --tagId <id> [--value <v>] [--chainId <c>]
or --labels '<json>' → POST a single label or batch upsert.
- profiles remove-label <address> --tagId <id> [--chainId <c>] →
DELETE the label from the profile.
Local validation: properties must be a non-empty JSON object; labels
must be either a single tagId or a non-empty JSON array; remove-label
requires tagId. Wired up tests for each validation path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the ad-hoc verb-noun commands onto the established CRUD verb
conventions used elsewhere in the CLI:
- profiles set-properties → profiles update
- profiles add-label → profiles labels create
- profiles remove-label → profiles labels delete
`labels` is now a proper sub-resource group under profiles (mirrors
the URL /v0/profiles/{address}/labels) so future label operations
slot in cleanly. Single-verb naming matches alerts/boards/charts/
contracts/segments. Tests renamed to track the new helper exports.
README rewritten to cover the full surface — auth (login/logout/
status), profiles (get, search, update, labels create/delete),
alerts, boards, charts, contracts, segments, query, import — plus
FilterCondition reference, response shapes, and output flags.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two big coverage gaps closed without a network-mock library:
1. parseApiError() — exported from src/lib/client.ts, the function the
axios response interceptor delegates to. Six tests cover the
canonical { error: { code, message, doc_url, param, details } }
envelope, fallback to axios message when no envelope, transport
errors with no response, and the multi-line message construction
(Param/Docs lines elided when absent).
2. Body builders — extracted from each *Run() helper into pure
build*Body() functions so we can test the camelCase→snake_case key
translation (triggerType→trigger_type, chainId→chain_id, etc.),
JSON parsing of nested fields (triggerFilters, recipient, abi,
events, filterSets, properties, labels), single-vs-batch label
dispatch, and what isn't included in update bodies (e.g. path
params don't leak in). 17 new tests across alerts, contracts,
segments, import, profiles update, and labels create/delete.
Net: 47 → 68 tests passing, no new dependencies, no behavior change in
the run helpers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
No description provided.