Documentation Index
Fetch the complete documentation index at: https://mintlify.com/sebamar88/bytekit/llms.txt
Use this file to discover all available pages before exploring further.
Powered by Mintlify
Auto-generate your docs
Best practices for error handling, performance optimization, tree-shaking, and testing with ByteKit
Documentation Index
Fetch the complete documentation index at: https://mintlify.com/sebamar88/bytekit/llms.txt
Use this file to discover all available pages before exploring further.
import { ApiError } from 'bytekit';
// Good: Handle errors explicitly
try {
const user = await client.get<User>('/users/1');
return user;
} catch (err) {
if (err instanceof ApiError) {
// Handle API errors
if (err.status === 404) {
return null; // User not found
} else if (err.status === 401) {
redirectToLogin();
} else {
showErrorToast(err.message);
}
}
// Re-throw unknown errors
throw err;
}
// Bad: Let errors propagate
const user = await client.get<User>('/users/1');
// Good: User-friendly messages
try {
await client.post('/users', userData);
toast.success('User created successfully!');
} catch (err) {
if (err instanceof ApiError) {
if (err.status === 400) {
toast.error('Please check your input and try again.');
} else if (err.status === 409) {
toast.error('A user with this email already exists.');
} else {
toast.error('Failed to create user. Please try again.');
}
}
}
// Bad: Raw error messages
try {
await client.post('/users', userData);
} catch (err) {
alert(err.message); // "Request failed with status 400"
}
import { createLogger, ApiError } from 'bytekit';
const logger = createLogger({ namespace: 'app' });
try {
const result = await client.post('/orders', orderData);
} catch (err) {
if (err instanceof ApiError) {
// Log full error details
logger.error('Order creation failed', {
status: err.status,
statusText: err.statusText,
body: err.body,
orderData
}, err);
// Show user-friendly message
toast.error('Failed to create order');
}
}
try {
const data = await client.get('/data');
} catch (err) {
if (err instanceof ApiError) {
if (err.isTimeout) {
toast.error('Request timed out. Please check your connection.');
} else if (err.status >= 500) {
toast.error('Server error. Please try again later.');
} else if (err.status === 401) {
toast.error('Please sign in to continue.');
redirectToLogin();
} else {
toast.error(err.message);
}
} else {
// Network error or other unexpected error
toast.error('Network error. Please check your connection.');
}
}
const queryClient = createQueryClient(apiClient, {
defaultStaleTime: 0,
defaultCacheTime: 300000 // 5 minutes
});
// Frequently changing: short stale time
const livePrice = await queryClient.query({
queryKey: ['price', symbol],
path: `/stocks/${symbol}/price`,
staleTime: 5000 // 5 seconds
});
// Rarely changing: long stale time
const config = await queryClient.query({
queryKey: ['config'],
path: '/config',
staleTime: 3600000 // 1 hour
});
// Static data: infinite stale time
const countries = await queryClient.query({
queryKey: ['countries'],
path: '/countries',
staleTime: Infinity
});
const queryClient = createQueryClient(apiClient, {
enableDeduplication: true
});
// These will only make ONE request
const [result1, result2, result3] = await Promise.all([
queryClient.query({ queryKey: ['data'], path: '/data' }),
queryClient.query({ queryKey: ['data'], path: '/data' }),
queryClient.query({ queryKey: ['data'], path: '/data' })
]);
const client = createApiClient({
baseUrl: 'https://api.example.com',
circuitBreaker: {
threshold: 5, // Open after 5 failures
timeout: 60000, // Stay open for 60s
resetTimeout: 30000 // Try to close after 30s
}
});
// Short timeout for health checks
const health = await client.get('/health', {
timeoutMs: 5000
});
// Longer timeout for file uploads
const upload = await client.post('/upload', formData, {
timeoutMs: 60000 // 1 minute
});
// Good: Single request for multiple items
const users = await client.get('/users', {
searchParams: { ids: [1, 2, 3, 4, 5] }
});
// Bad: Multiple requests
const users = await Promise.all([
client.get('/users/1'),
client.get('/users/2'),
client.get('/users/3'),
client.get('/users/4'),
client.get('/users/5')
]);
// Good: Named imports
import { createApiClient, createLogger } from 'bytekit';
// Bad: Import everything
import * as ByteKit from 'bytekit';
const client = ByteKit.createApiClient(...);
// Even better: Direct path imports
import { createApiClient } from 'bytekit/core';
import { createLogger } from 'bytekit/core';
import { StringUtils } from 'bytekit/helpers';
// Good: Only import what you use
import { createApiClient } from 'bytekit';
// Bad: Import unused utilities
import {
createApiClient,
createLogger, // Not used
Profiler, // Not used
StringUtils, // Not used
DateUtils // Not used
} from 'bytekit';
# Webpack Bundle Analyzer
npm install --save-dev webpack-bundle-analyzer
# Rollup Plugin Visualizer
npm install --save-dev rollup-plugin-visualizer
# Vite Bundle Analyzer
npm install --save-dev rollup-plugin-visualizer
import { vi, describe, it, expect } from 'vitest';
import type { ApiClient } from 'bytekit';
// Create mock client
const mockClient = {
get: vi.fn(),
post: vi.fn(),
put: vi.fn(),
delete: vi.fn()
} as unknown as ApiClient;
// Test
describe('UserService', () => {
it('should fetch user', async () => {
mockClient.get.mockResolvedValue({
id: 1,
name: 'John'
});
const service = new UserService(mockClient);
const user = await service.getUser('1');
expect(mockClient.get).toHaveBeenCalledWith('/users/1');
expect(user.name).toBe('John');
});
});
import { ApiError } from 'bytekit';
it('should handle 404 errors', async () => {
mockClient.get.mockRejectedValue(
new ApiError(404, 'Not Found', 'User not found')
);
const service = new UserService(mockClient);
const user = await service.getUser('999');
expect(user).toBeNull();
});
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { createApiClient } from 'bytekit';
const server = setupServer(
rest.get('https://api.example.com/users/:id', (req, res, ctx) => {
return res(
ctx.json({
id: req.params.id,
name: 'John Doe'
})
);
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
it('should fetch user from API', async () => {
const client = createApiClient({
baseUrl: 'https://api.example.com'
});
const user = await client.get('/users/1');
expect(user.name).toBe('John Doe');
});
it('should retry on failure', async () => {
let attempts = 0;
const server = setupServer(
rest.get('https://api.example.com/data', (req, res, ctx) => {
attempts++;
if (attempts < 3) {
return res(ctx.status(500));
}
return res(ctx.json({ success: true }));
})
);
const client = createApiClient({
baseUrl: 'https://api.example.com',
retryPolicy: { maxRetries: 3 }
});
const result = await client.get('/data');
expect(attempts).toBe(3);
expect(result.success).toBe(true);
});
// services/UserService.ts
import type { ApiClient } from 'bytekit';
export class UserService {
constructor(private client: ApiClient) {}
async getUser(id: string) {
return this.client.get<User>(`/users/${id}`);
}
async updateUser(id: string, data: Partial<User>) {
return this.client.put<User>(`/users/${id}`, data);
}
async deleteUser(id: string) {
return this.client.delete(`/users/${id}`);
}
}
// Usage
const userService = new UserService(apiClient);
const user = await userService.getUser('1');
// types/api.ts
export interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user';
createdAt: string;
}
export interface Post {
id: number;
title: string;
content: string;
authorId: number;
author?: User;
}
export interface PaginatedResponse<T> {
data: T[];
total: number;
page: number;
pageSize: number;
}
// lib/api.ts
import { createApiClient } from 'bytekit';
export const apiClient = createApiClient({
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000',
defaultHeaders: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
},
timeoutMs: Number(process.env.API_TIMEOUT) || 15000
});
// config/api.ts
import { createApiClient, createLogger } from 'bytekit';
const logger = createLogger({
namespace: 'api',
level: process.env.NODE_ENV === 'production' ? 'error' : 'debug'
});
export const apiClient = createApiClient({
baseUrl: process.env.API_URL,
logger,
retryPolicy: {
maxRetries: 3,
initialDelayMs: 1000
},
circuitBreaker: {
threshold: 5,
timeout: 60000
}
});
// Good: Redact sensitive data
logger.info('User login', {
userId: user.id,
email: user.email
// Don't log: password, tokens, credit cards
});
// Bad: Logging everything
logger.info('User login', user); // May contain password
const client = createApiClient({
baseUrl: process.env.NODE_ENV === 'production'
? 'https://api.example.com'
: 'http://localhost:3000'
});
const user = await client.get<User>('/users/1', {
validateResponse: {
id: { type: 'number', required: true },
email: { type: 'string', required: true },
role: { type: 'string', required: true }
}
});
const client = createApiClient({
baseUrl: 'https://api.example.com',
defaultHeaders: {
'Origin': window.location.origin
}
});
import { Profiler, createLogger } from 'bytekit';
const logger = createLogger({ namespace: 'perf' });
const profiler = new Profiler('api');
profiler.start('fetch-user');
const user = await client.get('/users/1');
profiler.end('fetch-user');
const timings = profiler.summary();
if (timings['fetch-user'] > 1000) {
logger.warn('Slow API response', { timings });
}
const queryClient = createQueryClient(apiClient, {
globalCallbacks: {
onError: (error, context) => {
// Send to error tracking service
Sentry.captureException(error, {
tags: {
url: context.url,
method: context.method
}
});
}
}
});
const logger = createLogger({
namespace: 'api',
transports: [
async (entry) => {
// Send to logging service
await fetch('https://logs.example.com/ingest', {
method: 'POST',
body: JSON.stringify({
level: entry.level,
message: entry.message,
context: entry.context,
timestamp: entry.timestamp
})
});
}
]
});