Skip to content

Quick Start

Learn the basics of fetchquack in just a few minutes.

First, create an instance of HttpClient:

import { HttpClient } from 'fetchquack';
const client = new HttpClient();
// Simple GET - response is automatically parsed as JSON
const users = await client.fetch<User[]>({
method: 'GET',
url: '/api/users'
});
console.log(users);
// With query parameters
const url = new URL('/users', 'https://api.example.com');
url.searchParams.set('page', '1');
url.searchParams.set('limit', '10');
const pagedUsers = await client.fetch<User[]>({
method: 'GET',
url: url.toString()
});
// Object bodies are automatically serialized to JSON
// Content-Type is auto-set to 'application/json' for object bodies
const newUser = await client.fetch<User>({
method: 'POST',
url: '/api/users',
body: {
name: 'John Doe',
email: 'john@example.com',
}
});
// PUT
await client.fetch({ method: 'PUT', url: '/api/users/1', body: { name: 'Jane Doe' } });
// PATCH
await client.fetch({ method: 'PATCH', url: '/api/users/1', body: { email: 'jane@example.com' } });
// DELETE
await client.fetch({ method: 'DELETE', url: '/api/users/1' });
const html = await client.fetch({
method: 'GET',
url: '/api/page',
parseJson: false
});
const imageData = await client.fetch({
method: 'GET',
url: '/api/image.png',
decodeToString: false // Returns Uint8Array instead of parsing as JSON/text
});
// imageData is a Uint8Array

Stream response data chunk by chunk. fetchStream() returns void and delivers data through callbacks. Use AbortController to cancel:

const controller = new AbortController();
client.fetchStream({
method: 'GET',
url: '/api/large-file',
signal: controller.signal,
decodeToString: true,
onData: (chunk) => {
console.log('Received chunk:', chunk);
},
onComplete: () => {
console.log('Stream finished!');
},
onError: (error) => {
console.error('Stream error:', error);
}
});
// Cancel at any time
// controller.abort();

Handle SSE with automatic reconnection. sse() also returns void and uses callbacks:

const controller = new AbortController();
client.sse({
method: 'GET',
url: '/api/events',
signal: controller.signal,
autoReconnect: true,
onEvent: (event) => {
console.log('Event:', event.data);
},
onError: (error) => {
console.error('Error:', error);
},
onComplete: () => {
console.log('Connection closed');
}
});
// Close the connection
// controller.abort();

Monitor upload and download progress:

const response = await client.fetch({
method: 'POST',
url: '/api/upload',
body: largeFile,
onUploadProgress: (progress) => {
console.log(`Upload: ${progress.percentage}%`);
},
onDownloadProgress: (progress) => {
console.log(`Download: ${progress.percentage}%`);
},
});

fetchquack provides detailed error information:

import { HttpError, HttpJsonParseError } from 'fetchquack';
try {
await client.fetch({ method: 'GET', url: '/api/data' });
} catch (error) {
if (error instanceof HttpJsonParseError) {
// JSON parsing failed
console.error('Invalid JSON:', error.responseText);
} else if (error instanceof HttpError) {
// HTTP error (4xx, 5xx) or network error
console.error(`HTTP ${error.statusCode}: ${error.message}`);
// statusCode is 0 for network errors or aborted requests
}
}

Use AbortController to cancel any request:

const controller = new AbortController();
const promise = client.fetch({
method: 'GET',
url: '/api/slow-endpoint',
signal: controller.signal
});
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
try {
const data = await promise;
} catch (error) {
if (error instanceof HttpError && error.statusCode === 0) {
console.log('Request was cancelled');
}
}

Add authentication or logging with interceptors globally:

import { HttpClient } from 'fetchquack';
import { authInterceptor } from 'fetchquack/interceptors/auth';
import { loggingInterceptor } from 'fetchquack/interceptors/logging';
const client = new HttpClient({
globalInterceptors: [
authInterceptor({ getToken: () => 'your-auth-token' }),
loggingInterceptor(),
],
});