Helpers
fetchAdapter, axiosAdapter, xhrAdapter, consoleSink, fileSink, createTrace, multiplex, loggerSink, the OTLP exporters, and memoryStore.
The exported helper functions you wire into a stitch: the default transport, the trace sinks (including OTLP export), the default store, and the schema adapter. Each signature is below; the guides cover usage in depth and are linked under See also.
Transport
fetchAdapter
The default fetch-based transport. Returns an Adapter backed by the global
fetch; it never throws on a non-2xx response — only network and abort errors
propagate, leaving the engine to decide what a status means.
import { } from 'stitchapi';
const = ();It accepts an optional FetchAdapterOptions to thread a per-stitch undici
dispatcher — an Agent for a proxy, a custom CA, or interface binding —
straight through as Node's non-standard dispatcher fetch init option. The
runtime stays zero-dependency, so StitchAPI never imports undici; you bring your
own Agent. An optional fetch override swaps the global fetch for testing or
custom runtimes. With no options, behavior is identical to fetchAdapter() (no
dispatcher is set).
import { , } from 'stitchapi';
// Your real `new Agent(...)` from undici is structurally an unknown dispatcher here —
// no undici import inside StitchAPI or this snippet.
declare const : unknown;
const = ({
: 'https://api.example.com/users/{id}',
: ({ : }),
});The axiosAdapter equivalent is axios's own httpAgent / httpsAgent, passed
through its defaults (axiosAdapter(axios, { httpsAgent })) — see below.
axiosAdapter
Route a stitch through a caller-supplied axios instance instead of fetch. The
runtime stays zero-dependency, so you pass your axios (or an axios.create())
rather than an import inside StitchAPI; body encoding, headers, and parsing match
fetchAdapter, so swapping transports never changes behavior. It is
buffered-only — it throws on a stream/sse surface; use fetchAdapter to
stream. It does report byte progress: the adapter wires axios's native
onUploadProgress/onDownloadProgress into onProgress (both phases), so an
upload bar works on a modern axios without leaving your instance.
import { type AxiosLike, , } from 'stitchapi';
// Your real axios instance is structurally an AxiosLike — no axios import needed here.
declare const : AxiosLike;
const = ({
: 'https://api.example.com/users/{id}',
: (),
});xhrAdapter
An XMLHttpRequest-backed transport whose reason to exist is upload progress
(fetch cannot report bytes sent). Browser-only by default; pass a constructor to
inject a polyfill or a fake. Buffered-only, like axiosAdapter.
import { , } from 'stitchapi';
const = ({
: 'POST',
: 'https://api.example.com/files',
: (), // defaults to globalThis.XMLHttpRequest
});Adapter capabilities
Each built-in adapter declares what it supports as an optional capabilities
descriptor on the returned function — { name?, supports }, where supports
lists the optional features the transport has ('stream', 'uploadProgress',
'downloadProgress'); anything not listed, it can't do.
| adapter | stream | uploadProgress | downloadProgress |
|---|---|---|---|
fetchAdapter | ✓ | — | ✓ |
xhrAdapter | — | ✓ | ✓ |
axiosAdapter | — | ✓ | ✓ |
Only fetchAdapter streams (xhr/axios buffer and reject stream); only fetch
cannot report upload progress. axiosAdapter wires axios's native
onUploadProgress/onDownloadProgress, so it needs an axios that supports them (v1+).
import { } from 'stitchapi';
// { name: 'fetchAdapter', supports: ['stream', 'downloadProgress'] }
const = ().;Declaring capabilities is opt-in: a custom adapter is still just
(req) => Promise<AdapterResponse>, and one that declares nothing is treated as
unknown — no checks run against it.
The engine checks supports for 'uploadProgress' to turn a silent footgun into a
teaching note. If a call passes onProgress with a request body and the active
adapter's supports omits 'uploadProgress' (only fetch, among the built-ins), the stitch emits one
info event — topic adapter.upload-progress-unsupported — through your trace
sink, pointing you at xhrAdapter:
onProgress is set with a request body, but fetchAdapter cannot report upload progress — only 'phase: download' events fire. Use xhrAdapter() to draw an upload progress bar.
It is a note, not an error: fetch still reports phase: 'download'
progress, so a download bar on a POST keeps working — only the upload phase is
dark. To see the note, attach any trace sink (e.g. consoleSink); to act on it,
switch the call to xhrAdapter().
Tracing & OTLP
Tracing is off by default — a stitch traces nothing until you pass a trace
sink (or set STITCH_TRACE_*). These are the sinks you reach for; see
Trace sinks for the full opt-in model.
consoleSink
A console-only sink: the colored one-line-per-event stream to stderr, nothing on
disk. The trace: 'console' shorthand resolves to this.
import { } from 'stitchapi';
const = ();fileSink
A file-only sink: append every event as JSONL to path (defaults to
~/.stitch/runs/proto.jsonl). Writing to disk is a side effect, so you pass it
explicitly — a stitch never opens a trace file on its own. An optional second
argument tunes privacy: maxBodyBytes (default 2048; false for full capture)
caps body/result truncation,
and redactHeaders widens the redaction denylist.
import { } from 'stitchapi';
const = ('./runs/today.jsonl', { : false });createTrace
Build a zero-infra trace sink: a compact one-line-per-event summary on the
console and/or an appended JSONL record per event. console defaults to true;
file defaults to a path under $HOME, or false to disable the JSONL stream;
maxBodyBytes and redactHeaders tune the JSONL sink's
privacy defaults
(header/URL redaction and body truncation are always applied to the file stream).
(This is the low-level builder behind consoleSink/fileSink; the off-by-default
behavior lives at the stitch's trace field, not here.)
import { } from 'stitchapi';
const = ({ : true, : false });multiplex
Fan one event stream out to several sinks — for example console/JSONL alongside OTLP — flushing each in turn.
import { , , } from 'stitchapi';
const = ((), ());loggerSink
Bridge the event stream to any host logger — pino, winston, the console,
anything with error / warn / info / debug methods (LoggerLike). It is
payload-free (logs only metadata — name, method, scrubbed URL, status, attempt
counts, drift path/level, timing — never the body, the result's data, or a delta
chunk) and maps each event to a level: result → info, error → error,
drift → the finding's level, start/progress/info/done → debug, and
delta is never logged. Override per type with levels. The logger-agnostic core
twin of @stitchapi/nest's nestLoggerSink.
import { } from 'stitchapi';
// `console` satisfies LoggerLike; pass `pino()` or a winston logger just the same.
const = (, { : { : 'debug' } });otlpSink
An opt-in OpenTelemetry sink: it maps each stitch call's events to a single OTel
CLIENT span and hands finished spans to a SpanExporter. With no exporter
supplied it uses otlpHttpExporter. Configured by OtlpOptions (below).
import { } from 'stitchapi';
const = ({ : 'https://api.example.com:4318' });otlpHttpExporter
The default exporter: POST spans as OTLP/JSON to ${endpoint}/v1/traces. The
endpoint defaults to OTEL_EXPORTER_OTLP_ENDPOINT or http://localhost:4318.
Fire-and-forget — a missing collector never breaks a stitch call.
import { } from 'stitchapi';
const = ({
: 'https://api.example.com:4318',
: { : 'Bearer token' },
});toOtlpJson
Serialize finished spans to the OTLP/JSON ResourceSpans shape a collector
accepts on /v1/traces — useful for a custom SpanExporter.
import { } from 'stitchapi';
const = ([]);OtlpOptions
Prop
Type
Store
memoryStore
The default in-memory StitchStore: single-process, with TTL and atomic
increment. Swap it for a Redis/Postgres-backed store to make throttling
distributed and sessions shared across workers, with no change to the call site.
import { } from 'stitchapi';
const = ();