🌐 Frontend TypeScript - Consuming & Producing B-FAST¶
The bfast-client package is the ultra-fast binary serialization, streaming, and decoding library for JavaScript and TypeScript.
It supports Dual-Module (ESM & CommonJS), Browsers, Node.js, Bun, Deno, and Cloudflare Workers with automatic, zero-config LZ4 compression.
📦 Installation¶
⚡ Quick Start: bfastFetch¶
The fastest and most ergonomic way to communicate with B-FAST endpoints:
import { bfastFetch } from 'bfast-client';
interface User {
id: number;
name: string;
role: string;
}
// GET: Automatically sets Accept headers and decodes the binary response
const users = await bfastFetch<User[]>('/api/users');
console.log(users[0].name);
// POST: Automatically serializes JS objects to B-FAST binary payload
const created = await bfastFetch<User>('/api/users', {
method: 'POST',
body: { name: 'Alice', role: 'admin' },
compress: true, // optional LZ4 compression
});
🔄 Bidirectional Serialization & Decoding¶
Binary Encoding (BFastEncoder)¶
Serializes native JavaScript objects, dates, arrays, and typed arrays directly into the binary wire format:
import { BFastEncoder } from 'bfast-client';
const payload = {
userId: 42,
username: 'alice',
tags: ['admin', 'dev'],
createdAt: new Date(),
matrix: new Float64Array([1.5, 2.5, 3.5]),
};
// Generates pure B-FAST Uint8Array binary
const bytes = BFastEncoder.encode(payload);
// With LZ4 compression enabled
const compressedBytes = BFastEncoder.encode(payload, { compress: true });
Binary Decoding (BFastDecoder)¶
import { BFastDecoder } from 'bfast-client';
// Decodes ArrayBuffer or Uint8Array
const data = BFastDecoder.decode<User>(buffer);
// Zero-copy typed array extraction (Float64Array)
const numbers = BFastDecoder.decode(buffer, { typedArrays: true });
⚡ Transparent Compression (Zero Config)¶
bfast-client handles LZ4 compression and decompression automatically and transparently with zero setup:
- Zero Configuration: No bundler plugins (Vite, Webpack, Next.js), external assets to serve, or native build steps required.
- Automatic Detection: When decoding any compressed payload (
compress: true), the client detects and decompresses data instantly. - Universal: Works out of the box in browsers, Node.js, Bun, Deno, and Cloudflare Workers.
🌊 Real-Time Streaming (Bidirectional)¶
Consuming Streams (decodeReadableStream and decodeStream)¶
Consume continuous data frames emitted by BFastStreamingResponse or MCP servers without blocking the user interface:
import { decodeReadableStream, decodeStream } from 'bfast-client';
// In browsers with Fetch API ReadableStream
const response = await fetch('/api/stream-users');
for await (const user of decodeReadableStream<User>(response.body!)) {
console.log('Real-time user received:', user);
}
// Universal (ReadableStream or Node.js async iterators)
for await (const item of decodeStream(response.body!)) {
console.log('Stream item received:', item);
}
Encoding Stream Frames (BFastStreamEncoder)¶
import { BFastStreamEncoder } from 'bfast-client';
// Stream handshake
const handshake = BFastStreamEncoder.getHandshake();
// Encode JavaScript objects into binary stream frames
const frame = BFastStreamEncoder.encodeFrame({ sensor: 'A', value: 42 });
// End of Stream (EOS) marker frame
const eos = BFastStreamEncoder.getEosFrame();
🧩 Framework Integrations¶
TanStack Query (React Query, Vue Query, Svelte, Solid)¶
The recommended way to integrate B-FAST with TanStack Query is using bfastQueryOptions:
import { useQuery } from '@tanstack/react-query';
import { bfastQueryOptions } from 'bfast-client';
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
export function UserProfile({ id }: { id: number }) {
const { data: user, isLoading } = useQuery(
bfastQueryOptions<User>({
queryKey: ['user', id],
url: `/api/users/${id}`,
schema: UserSchema, // Runtime validation & strict typing
staleTime: 10_000,
})
);
if (isLoading) return <span>Loading...</span>;
return <h1>{user?.name}</h1>;
}
Infinite Query (Pagination & Infinite Scroll)¶
import { useInfiniteQuery } from '@tanstack/react-query';
import { bfastInfiniteQueryOptions } from 'bfast-client';
const queryOptions = bfastInfiniteQueryOptions<User[]>({
queryKey: ['users', 'infinite'],
initialPageParam: 1,
getUrl: (page) => `/api/users?page=${page}`,
getNextPageParam: (lastPage, allPages, lastParam) => {
return lastPage.length === 20 ? (lastParam as number) + 1 : undefined;
},
});
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(queryOptions);
Runtime Schema Validation (Zod / Standard Schema)¶
bfast-client universally supports the Standard Schema specification (~standard for Zod 3.24+, Valibot 1.0+, ArkType 2.0+) and classic safeParse/parse validators:
import { BFastDecoder, bfastFetch, BFastValidationError } from 'bfast-client';
import { z } from 'zod';
const MetricsSchema = z.object({
cpu: z.number(),
memory: z.number(),
nodes: z.array(z.string()),
});
// 1. In bfastFetch:
try {
const metrics = await bfastFetch('/api/metrics', { schema: MetricsSchema });
} catch (err) {
if (err instanceof BFastValidationError) {
console.error('Schema validation issues:', err.issues);
}
}
// 2. In synchronous BFastDecoder:
const metrics = BFastDecoder.decode(buffer, { schema: MetricsSchema });
// 3. In streams (validates every incoming frame):
const streamDecoder = new BFastStreamDecoder({ schema: MetricsSchema });
Custom React Hook¶
import { useState, useEffect } from 'react';
import { bfastFetch } from 'bfast-client';
export function useBFastData<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
let active = true;
bfastFetch<T>(url)
.then(res => { if (active) setData(res); })
.catch(err => { if (active) setError(err); })
.finally(() => { if (active) setLoading(false); });
return () => { active = false; };
}, [url]);
return { data, loading, error };
}
Axios Interceptor¶
import axios from 'axios';
import { BFastDecoder } from 'bfast-client';
axios.interceptors.response.use(response => {
if (response.headers['content-type'] === 'application/x-bfast') {
response.data = BFastDecoder.decode(response.data);
}
return response;
});
🛡️ Error Handling¶
import { BFastDecoder, BFastError, BFastValidationError } from 'bfast-client';
try {
const data = BFastDecoder.decode(buffer, { schema: UserSchema });
} catch (error) {
if (error instanceof BFastValidationError) {
console.error('Payload validation failure:', error.issues);
} else if (error instanceof BFastError) {
console.error('B-FAST binary decoding error:', error.message);
}
}
🌐 Compatibility¶
- Browsers: Chrome 60+, Firefox 55+, Safari 12+, Edge 79+
- Runtimes: Node.js 14+, Bun, Deno, Cloudflare Workers
- Module Formats: Dual Module (native ESM + CommonJS)