BREAKING CHANGE(client/streaming): Unify streaming APIs: remove raw()/streamNode() and standardize on web ReadableStream across runtimes
This commit is contained in:
183
readme.md
183
readme.md
@@ -182,11 +182,11 @@ async function downloadImage(url: string) {
|
||||
return Buffer.from(buffer); // Convert ArrayBuffer to Buffer if needed
|
||||
}
|
||||
|
||||
// Streaming response (Web Streams API)
|
||||
// Streaming response (Web Streams API - cross-platform)
|
||||
async function streamLargeFile(url: string) {
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
|
||||
// Get a web-style ReadableStream (works in both Node.js and browsers)
|
||||
// Get a web-style ReadableStream (works everywhere)
|
||||
const stream = response.stream();
|
||||
|
||||
if (stream) {
|
||||
@@ -204,12 +204,14 @@ async function streamLargeFile(url: string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Node.js specific stream (only in Node.js environment)
|
||||
// Convert to Node.js stream if needed (Node.js only)
|
||||
async function streamWithNodeApi(url: string) {
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
|
||||
// Only available in Node.js, throws error in browser/Bun/Deno
|
||||
const nodeStream = response.streamNode();
|
||||
// Convert web stream to Node.js stream
|
||||
import { Readable } from 'stream';
|
||||
const webStream = response.stream();
|
||||
const nodeStream = Readable.fromWeb(webStream);
|
||||
|
||||
nodeStream.on('data', (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes of data`);
|
||||
@@ -230,8 +232,7 @@ The response object provides these methods:
|
||||
- `text(): Promise<string>` - Get response as text
|
||||
- `arrayBuffer(): Promise<ArrayBuffer>` - Get response as ArrayBuffer
|
||||
- `stream(): ReadableStream<Uint8Array> | null` - Get web-style ReadableStream (cross-platform)
|
||||
- `streamNode(): NodeJS.ReadableStream` - Get Node.js stream (Node.js only, throws in browser/Bun/Deno)
|
||||
- `raw(): Response | http.IncomingMessage` - Get the underlying platform response
|
||||
- `raw(): Response | http.IncomingMessage` - Get the underlying platform response object
|
||||
|
||||
Each body method can only be called once per response, similar to the fetch API.
|
||||
|
||||
@@ -368,24 +369,7 @@ async function streamData(dataSource: Readable) {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
// Advanced: Full control over request streaming (Node.js only)
|
||||
async function customStreaming() {
|
||||
const response = await SmartRequest.create()
|
||||
.url('https://api.example.com/stream')
|
||||
.raw((request) => {
|
||||
// Custom streaming logic - you have full control
|
||||
request.write('chunk1');
|
||||
request.write('chunk2');
|
||||
|
||||
// Stream from another source
|
||||
someReadableStream.pipe(request);
|
||||
})
|
||||
.post();
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
// Send Uint8Array (works in both Node.js and browser)
|
||||
// Send Uint8Array (works everywhere)
|
||||
async function uploadBinaryData() {
|
||||
const data = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
|
||||
|
||||
@@ -411,11 +395,6 @@ async function uploadBinaryData() {
|
||||
- ✅ Web ReadableStream works everywhere (Node.js, Bun, Deno, browsers)
|
||||
- ⚠️ Node.js streams only work in Node.js (automatically converted to web streams in Bun/Deno)
|
||||
|
||||
- **`.raw(streamFunc)`** - Advanced control over request streaming
|
||||
- `streamFunc`: Function that receives the raw request object for custom streaming
|
||||
- ❌ **Node.js only** - not supported in browsers, Bun, or Deno
|
||||
- Use for advanced scenarios like chunked transfer encoding
|
||||
|
||||
These methods are particularly useful for:
|
||||
- Uploading large files without loading them into memory
|
||||
- Streaming real-time data to servers
|
||||
@@ -687,13 +666,12 @@ const response = await SmartRequest.create()
|
||||
})
|
||||
.get();
|
||||
|
||||
// Bun uses web streams - streamNode() throws an error
|
||||
// Bun uses web streams natively
|
||||
const streamResponse = await SmartRequest.create()
|
||||
.url('https://api.example.com/data')
|
||||
.get();
|
||||
|
||||
const webStream = streamResponse.stream(); // ✅ Use web streams in Bun
|
||||
// streamNode() is not available - throws error directing you to use stream()
|
||||
```
|
||||
|
||||
### Deno-Specific Options
|
||||
@@ -716,13 +694,12 @@ const response = await SmartRequest.create()
|
||||
// Remember to clean up clients when done
|
||||
client.close();
|
||||
|
||||
// Deno uses web streams - streamNode() throws an error
|
||||
// Deno uses web streams natively
|
||||
const streamResponse = await SmartRequest.create()
|
||||
.url('https://api.example.com/data')
|
||||
.get();
|
||||
|
||||
const webStream = streamResponse.stream(); // ✅ Use web streams in Deno
|
||||
// streamNode() is not available - throws error directing you to use stream()
|
||||
```
|
||||
|
||||
## Complete Example: Building a REST API Client
|
||||
@@ -838,6 +815,144 @@ async function fetchWithErrorHandling(url: string) {
|
||||
|
||||
## Migrating from Earlier Versions
|
||||
|
||||
### From v4.x to v5.x
|
||||
|
||||
Version 5.0 completes the transition to modern web standards by removing Node.js-specific streaming APIs:
|
||||
|
||||
#### **Breaking Changes**
|
||||
|
||||
1. **`.streamNode()` Method Removed**
|
||||
- The `.streamNode()` method has been removed from all response objects
|
||||
- Use the cross-platform `.stream()` method instead, which returns a web `ReadableStream<Uint8Array>`
|
||||
- For Node.js users who need Node.js streams, convert using `Readable.fromWeb()`
|
||||
|
||||
```typescript
|
||||
// ❌ Before (v4.x) - Node.js only
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const nodeStream = response.streamNode();
|
||||
|
||||
// ✅ After (v5.x) - Cross-platform
|
||||
import { Readable } from 'stream';
|
||||
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const webStream = response.stream();
|
||||
const nodeStream = Readable.fromWeb(webStream); // Convert to Node.js stream
|
||||
```
|
||||
|
||||
2. **Request `.raw()` Method Removed**
|
||||
- The `.raw(streamFunc)` method has been removed from the SmartRequest client
|
||||
- Use `.stream()` with a web `ReadableStream` instead for request body streaming
|
||||
- Node.js users can create web streams from Node.js streams using `Readable.toWeb()`
|
||||
|
||||
```typescript
|
||||
// ❌ Before (v4.x) - Node.js only
|
||||
const response = await SmartRequest.create()
|
||||
.url(url)
|
||||
.raw((request) => {
|
||||
request.write('chunk1');
|
||||
request.write('chunk2');
|
||||
request.end();
|
||||
})
|
||||
.post();
|
||||
|
||||
// ✅ After (v5.x) - Cross-platform
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(new TextEncoder().encode('chunk1'));
|
||||
controller.enqueue(new TextEncoder().encode('chunk2'));
|
||||
controller.close();
|
||||
}
|
||||
});
|
||||
|
||||
const response = await SmartRequest.create()
|
||||
.url(url)
|
||||
.stream(stream)
|
||||
.post();
|
||||
|
||||
// Or convert from Node.js stream (Node.js only)
|
||||
import { Readable } from 'stream';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const nodeStream = fs.createReadStream('file.txt');
|
||||
const webStream = Readable.toWeb(nodeStream);
|
||||
|
||||
const response = await SmartRequest.create()
|
||||
.url(url)
|
||||
.stream(webStream)
|
||||
.post();
|
||||
```
|
||||
|
||||
3. **Response `.raw()` Method Preserved**
|
||||
- The `response.raw()` method is still available for accessing platform-specific response objects
|
||||
- Returns `http.IncomingMessage` in Node.js or `Response` in other runtimes
|
||||
- Use for advanced scenarios requiring access to raw platform objects
|
||||
|
||||
```typescript
|
||||
// ✅ Still works in v5.x
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const rawResponse = response.raw(); // http.IncomingMessage or Response
|
||||
```
|
||||
|
||||
#### **Migration Guide**
|
||||
|
||||
**For Response Streaming:**
|
||||
|
||||
```typescript
|
||||
// Before (v4.x)
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const nodeStream = response.streamNode();
|
||||
|
||||
nodeStream.on('data', (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes`);
|
||||
});
|
||||
|
||||
// After (v5.x) - Option 1: Use web streams directly
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const webStream = response.stream();
|
||||
|
||||
if (webStream) {
|
||||
const reader = webStream.getReader();
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
console.log(`Received ${value.length} bytes`);
|
||||
}
|
||||
reader.releaseLock();
|
||||
}
|
||||
|
||||
// After (v5.x) - Option 2: Convert to Node.js stream (Node.js only)
|
||||
import { Readable } from 'stream';
|
||||
|
||||
const response = await SmartRequest.create().url(url).get();
|
||||
const webStream = response.stream();
|
||||
const nodeStream = Readable.fromWeb(webStream);
|
||||
|
||||
nodeStream.on('data', (chunk) => {
|
||||
console.log(`Received ${chunk.length} bytes`);
|
||||
});
|
||||
```
|
||||
|
||||
**For Request Streaming:**
|
||||
|
||||
Node.js streams are still accepted by the `.stream()` method and automatically converted internally. No changes required for most use cases:
|
||||
|
||||
```typescript
|
||||
// ✅ Still works in v5.x
|
||||
import * as fs from 'fs';
|
||||
|
||||
const fileStream = fs.createReadStream('large-file.bin');
|
||||
const response = await SmartRequest.create()
|
||||
.url('https://api.example.com/upload')
|
||||
.stream(fileStream, 'application/octet-stream')
|
||||
.post();
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- ✅ True cross-platform compatibility
|
||||
- ✅ Modern web standards
|
||||
- ✅ Cleaner API surface
|
||||
- ✅ Single streaming approach works everywhere
|
||||
|
||||
### From v3.x to v4.x
|
||||
|
||||
Version 4.0 adds comprehensive cross-platform support:
|
||||
|
||||
Reference in New Issue
Block a user