Area: sdk — silent no-op · found by CodeRabbit on #456
PipeRef.fetch(opts?: RequestOptions) accepts the same per-call options type as the query builder, which carries limit — but it forwards only signal:
// clients/ts/src/pipes.ts:28-37
async fetch(opts?: RequestOptions): Promise<Result<Row[]>> {
const { data, error } = await request<Row[]>(this._ctx, {
method: "POST",
path: `/v1/pipes/${encodeURIComponent(this._name)}`,
body: this._params ?? {},
signal: opts?.signal, // <- opts.limit is never read
});
So wh.pipe('top_pages').fetch({ limit: 10 }) type-checks, runs, and returns whatever the pipe's own SQL returns. The caller gets no error and no indication the bound was ignored.
The other two implementations of the same signature do honour it — QueryBuilder.fetch (query-builder.ts:141, opts?.limit ?? this._state.limit ?? DEFAULT_LIMIT) and TableRef.fetch (table.ts:63, .limit(opts?.limit ?? 1000)) — so the inconsistency is within one shared type, which is what makes it easy to hit.
Limiting a pipe genuinely requires an operator-defined {{limit}} SQL parameter supplied via wh.pipe(name, params); a client-side row cap isn't something the pipes endpoint offers. So the fix is about the surface, not adding a feature.
Pre-existing, not introduced by #456: origin/main has the identical body with the type spelled FetchOptions. #456 only renamed the type, so it neither caused nor worsened this — filing rather than folding it in, to keep that PR's diff about the HTTP-customization surface.
Options
- Give
PipeRef.fetch a signal-only parameter type (Pick<RequestOptions, "signal">, or a named AbortOptions). Honest surface; a caller passing limit gets a compile error pointing at the real mechanism. Technically breaking for anyone passing limit today, though it never did anything.
- Honour it client-side by truncating the returned rows. Cheap, but invents a semantic the endpoint doesn't have and hides how much work the server did.
- Document it only. Weakest — the type still advertises it.
Option 1 looks right, ideally with the JSDoc naming wh.pipe(name, { limit }) as the actual route.
Same class as #280 (QueryBuilder.cacheTTL() is a silent no-op) — worth checking whether any other per-call option is accepted and dropped while someone is in here.
— Filed by Claude Opus 5, via Claude Code
Area: sdk — silent no-op · found by CodeRabbit on #456
PipeRef.fetch(opts?: RequestOptions)accepts the same per-call options type as the query builder, which carrieslimit— but it forwards onlysignal:So
wh.pipe('top_pages').fetch({ limit: 10 })type-checks, runs, and returns whatever the pipe's own SQL returns. The caller gets no error and no indication the bound was ignored.The other two implementations of the same signature do honour it —
QueryBuilder.fetch(query-builder.ts:141,opts?.limit ?? this._state.limit ?? DEFAULT_LIMIT) andTableRef.fetch(table.ts:63,.limit(opts?.limit ?? 1000)) — so the inconsistency is within one shared type, which is what makes it easy to hit.Limiting a pipe genuinely requires an operator-defined
{{limit}}SQL parameter supplied viawh.pipe(name, params); a client-side row cap isn't something the pipes endpoint offers. So the fix is about the surface, not adding a feature.Pre-existing, not introduced by #456:
origin/mainhas the identical body with the type spelledFetchOptions. #456 only renamed the type, so it neither caused nor worsened this — filing rather than folding it in, to keep that PR's diff about the HTTP-customization surface.Options
PipeRef.fetcha signal-only parameter type (Pick<RequestOptions, "signal">, or a namedAbortOptions). Honest surface; a caller passinglimitgets a compile error pointing at the real mechanism. Technically breaking for anyone passinglimittoday, though it never did anything.Option 1 looks right, ideally with the JSDoc naming
wh.pipe(name, { limit })as the actual route.Same class as #280 (
QueryBuilder.cacheTTL()is a silent no-op) — worth checking whether any other per-call option is accepted and dropped while someone is in here.— Filed by Claude Opus 5, via Claude Code