Skip to content

feat(turbopuffer): add @distilled.cloud/turbopuffer SDK#357

Open
agcty wants to merge 2 commits into
alchemy-run:mainfrom
agcty:turbopuffer
Open

feat(turbopuffer): add @distilled.cloud/turbopuffer SDK#357
agcty wants to merge 2 commits into
alchemy-run:mainfrom
agcty:turbopuffer

Conversation

@agcty

@agcty agcty commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Adds @distilled.cloud/turbopuffer — a spec-generated SDK for Turbopuffer, following the existing stripe/neon package pattern: a hand-written framework (client/credentials/errors/traits/retry over @distilled.cloud/core) + operations generated from the official OpenAPI spec.

  • Spec submodule: packages/turbopuffer/specs/turbopuffer-openapiturbopuffer/turbopuffer-openapi (branch next), wired the same way as stripestripe/openapi.
  • Auth/transport: Bearer API-key, region-parameterized base URL (https://{region}.turbopuffer.com).
  • 14 operations: 11 generated (ListNamespaces, WriteNamespace, QueryNamespace, DeleteNamespace, GetNamespaceSchema/UpdateNamespaceSchema, GetNamespaceMetadata/UpdateNamespaceMetadata, HintCacheWarm, DebugRecall, ExplainQuery) + 3 hand-authored (see below).

Two spec specifics worth a maintainer eye

The Turbopuffer OpenAPI spec has two traits the other packages' specs don't, handled as follows — happy to change the approach if you'd prefer something else:

  1. The spec omits operationIds. Rather than special-casing the generator, I added them via the standard patches/ mechanism — patches/001-add-operation-ids.patch.json (RFC-6902, same shape as neon's patches) injects the operationIds before generation, so scripts/generate.ts stays a thin wrapper. (Alternatively these could be contributed upstream to turbopuffer-openapi — open question.)

  2. Stainless ?stainless_overload= virtual paths. Three operations (BranchFromNamespace, CopyFromNamespace, MultiQueryNamespace) are modelled in the spec as multiple request shapes on a single POST method+path via Stainless's ?stainless_overload= convention, which the shared generator (one operation per method+path) can't express. The patch removes those virtual paths from generation, and the three ops are hand-authored in src/operations/manual/ matching the generated format — clobber-protected (the generator never touches manual/, and the barrel re-exports it). If the generator gains overload support later, these can move back to generation.

Checks

bun run generate (11 ops, 0 lint) · bun run check (tsgo + oxlint + oxfmt) ✅ · bun run build ✅ · all 14 operations exported.

🤖 Generated with Claude Code

agcty and others added 2 commits June 26, 2026 15:04
Spec-generated SDK for Turbopuffer, following the stripe/neon package pattern:
hand-written framework (client/credentials/errors/traits/retry over
@distilled.cloud/core, Bearer API-key auth, region-parameterized base URL) +
operations generated from the turbopuffer-openapi spec submodule.

Known limitations (turbopuffer spec specifics, flagged for review):
- The spec omits operationIds; generate.ts injects them via a lookup map
  (candidate for a patches/ entry or an upstream turbopuffer-openapi fix).
- 3 operations using Stainless ?stainless_overload= aliases on a shared
  method+path (BranchFromNamespace, CopyFromNamespace, MultiQueryNamespace)
  are not yet generated — needs generator support or manual operation files.
…erload ops

Make the SDK idiomatic with the rest of the Distilled packages:

- Move operationId injection out of the generate script and into
  patches/001-add-operation-ids.patch.json. The shared generator applies
  patchDir patches before it extracts operations (and detectVersion only
  reads spec.openapi), so a patch can supply the operationIds the turbopuffer
  spec omits. The same patch removes the three Stainless `?stainless_overload=`
  virtual paths. generate.ts is now a thin wrapper: the only pre-step left is
  the unavoidable YAML->JSON parse (the generator reads JSON only).

- Hand-author the three Stainless-overload operations the generator can't
  model (multiple body variants on one real method+path): BranchFromNamespace,
  CopyFromNamespace, MultiQueryNamespace, in src/operations/manual/. Bodies and
  responses are taken from the spec's overload entries; format mirrors a
  generated op. The generator rewrites operations/index.ts each run, so the
  manual barrel is re-exported by appending to it in generate.ts.

All 14 operations are exported. generate + check + build pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@agcty agcty marked this pull request as ready for review June 26, 2026 13:35
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.

1 participant