Runtime Adapters
@t-req/core uses adapters to abstract filesystem and network operations, making it work across Node.js, Bun, and desktop environments like Tauri.
Two Types of Adapters
Section titled “Two Types of Adapters”IO Adapter
Section titled “IO Adapter”Handles filesystem operations (reading .http files, loading referenced files):
interface IO { readFile(path: string): Promise<string>; readBinaryFile(path: string): Promise<Uint8Array>; resolvePath(base: string, relative: string): string;}Transport Adapter
Section titled “Transport Adapter”Handles HTTP execution:
interface Transport { execute(request: ExecuteRequest): Promise<Response>;}Node.js Setup
Section titled “Node.js Setup”In Node.js, you must provide an IO adapter for file-based operations:
import { createClient } from '@t-req/core';import { createNodeIO } from '@t-req/core/runtime';
const client = createClient({ io: createNodeIO(),});
// Now you can run from filesconst response = await client.run('./api/users.http');Without the IO adapter, client.run() will fail. However, client.runString() always works since it doesn’t need filesystem access.
Bun Setup
Section titled “Bun Setup”Bun works out of the box—@t-req/core automatically uses Bun’s filesystem APIs when no IO adapter is provided:
import { createClient } from '@t-req/core';
const client = createClient();
// Works without explicit IO adapterconst response = await client.run('./api/users.http');Desktop Apps (Tauri)
Section titled “Desktop Apps (Tauri)”For Tauri or Electron apps, the renderer process typically can’t access the filesystem directly. Use runString() with content from your backend:
import { createClient } from '@t-req/core';
const client = createClient();
// Get .http content from Tauri backendconst httpContent = await invoke('read_http_file', { path: './api/users.http' });
// Run from string - no filesystem access neededconst response = await client.runString(httpContent, { variables: { userId: '123' },});Custom IO Adapter for Tauri
Section titled “Custom IO Adapter for Tauri”If you need file references (< ./payload.json) to work, create a custom IO adapter that bridges to your backend:
import { createClient } from '@t-req/core';import { invoke } from '@tauri-apps/api/core';
const tauriIO = { async readFile(path: string): Promise<string> { return invoke('read_file', { path }); }, async readBinaryFile(path: string): Promise<Uint8Array> { const bytes = await invoke('read_binary_file', { path }); return new Uint8Array(bytes); }, resolvePath(base: string, relative: string): string { // Implement path resolution logic return `${base}/${relative}`; },};
const client = createClient({ io: tauriIO,});Custom Transport
Section titled “Custom Transport”Override the default fetch-based transport for custom HTTP handling:
import { createClient } from '@t-req/core';import { createFetchTransport } from '@t-req/core/runtime';
// Custom fetch with loggingconst customFetch = async (url, init) => { console.log(`Fetching: ${url}`); const response = await fetch(url, init); console.log(`Response: ${response.status}`); return response;};
const client = createClient({ transport: createFetchTransport(customFetch),});Engine with Explicit Adapters
Section titled “Engine with Explicit Adapters”The low-level engine API requires explicit adapters:
import { createEngine } from '@t-req/core';import { createFetchTransport, createNodeIO } from '@t-req/core/runtime';
const engine = createEngine({ io: createNodeIO(), transport: createFetchTransport(fetch), onEvent: (e) => console.log(e),});
// Run from fileawait engine.runFile('./api/users.http');
// Run from string (no IO needed)await engine.runString('GET https://example.com\n');When IO is Required
Section titled “When IO is Required”| Operation | IO Required |
|---|---|
client.run('./file.http') | Yes |
client.runString(content) | No |
File reference < ./payload.json | Yes |
File upload file = @./upload.pdf | Yes |
| Inline body content | No |
Runtime Detection
Section titled “Runtime Detection”@t-req/core automatically detects Bun and uses native APIs. For other environments, provide the appropriate adapters:
import { createClient } from '@t-req/core';import { createNodeIO } from '@t-req/core/runtime';
const client = createClient({ // Only needed in Node.js - Bun auto-detects io: typeof Bun !== 'undefined' ? undefined : createNodeIO(),});