-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Problem
The current @logosdx/fetch implementation cannot support streaming responses (SSE, chunked transfers, etc.) because the response body is fully consumed before returning to the caller.
In engine.ts, the #makeCall method always waits for the entire response:
const [data, parseErr] = await attempt(async () => {
const { type, isJson } = this.#determineType(response);
if (isJson) {
const text = await response.text(); // ← Blocks until stream closes
return text ? JSON.parse(text) : null;
}
else {
return await response[type](); // ← Also blocks
}
});This means SSE endpoints would block until the entire session ends before returning any data.
Proposed Solution
Add a 'stream' type that bypasses response parsing and returns the raw Response object.
Per-Request Stream Configuration
Streaming should be configurable on individual requests via a stream option:
// Option 1: Simple boolean
const { data: response } = await api.get('/api/events', {
stream: true
});
// Option 2: Explicit type (existing pattern)
const { data: response } = await api.get('/api/events', {
type: 'stream'
});This allows mixing streaming and non-streaming requests to the same endpoint based on context.
Implementation
// In #makeCall, before parsing:
if (type === 'stream' || config.stream === true) {
return {
data: response, // Raw Response - user calls response.body.getReader()
headers: Object.fromEntries(response.headers),
status: response.status,
request: new Request(url, fetchOpts),
config
};
}Changes Required
| File | Change |
|---|---|
types.ts |
Add 'stream' to the Type union |
types.ts |
Add optional stream?: boolean to request config |
engine.ts |
Skip body consumption when type === 'stream' or stream: true, return raw Response |
helpers.ts |
Add validation to warn/disable caching and deduplication for stream requests |
| Tests | Add streaming response test cases |
| Docs | Update with streaming usage examples |
Usage Example
const { data: response } = await api.get('/api/events', {
stream: true
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// Parse SSE: data: {...}\n\n
}Benefits Preserved for Streaming Requests
- Request building (headers, params, base URL)
- Interceptors/middleware on the request side
- AbortController integration
- Authentication headers
- Event hooks (
fetch-before, etc.)
Features Disabled for Streams
- Response body parsing (user handles)
- Caching (streams can only be read once)
- Deduplication (streams can't be shared)
- Response transformation
Notes
- Request body streaming is already supported (sending
ReadableStreamas payload works today) - This change is localized and should not affect existing functionality
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
No labels