Skip to content

Latest commit

 

History

History
216 lines (163 loc) · 3.6 KB

File metadata and controls

216 lines (163 loc) · 3.6 KB

Create Client

Use createClient to create a reusable HTTP client instance.

Basic client

import { createClient } from '@dfsync/client';

const client = createClient({
  baseURL: 'https://api.example.com',
});

Client with timeout

const client = createClient({
  baseUrl: 'https://api.example.com',
  timeout: 5000,
});

Client with default headers

const client = createClient({
  baseUrl: 'https://api.example.com',
  headers: {
    'x-service-name': 'billing-worker',
  },
});

Client with custom fetch

const client = createClient({
  baseUrl: 'https://api.example.com',
  fetch: globalThis.fetch,
});

Client configuration

type ClientConfig = {
  baseUrl: string;
  timeout?: number;
  headers?: Record<string, string>;
  fetch?: typeof globalThis.fetch;
  auth?: {
    // see Auth section
  };
  hooks?: {
    // see Hooks section
  };
};

HTTP methods

The client provides a predictable set of methods:

client.get(path, options?)
client.delete(path, options?)

client.post(path, body?, options?)
client.put(path, body?, options?)
client.patch(path, body?, options?)

client.request(config)

Body vs options

  • get and delete do not accept body
  • post, put, and patch accept request body as the second argument
  • options is used for headers, query, timeout, retry, and other settings

GET request

type User = {
  id: string;
  name: string;
};

const user = await client.get<User>('/users/1');

GET with query params

const users = await client.get('/users', {
  query: {
    page: 1,
    active: true,
  },
});

POST request

const created = await client.post('/users', {
  name: 'Tom',
  email: 'tom@example.com',
});

PUT request

const updated = await client.put('/users/1', {
  name: 'Tom Updated',
});

PATCH request

const updatedUser = await client.patch('/users/1', {
  name: 'Jane',
});

DELETE request

const result = await client.delete('/users/1');

Request options

type RequestOptions = {
  query?: Record<string, string | number | boolean | null | undefined>;
  headers?: Record<string, string>;
  timeout?: number;
  retry?: RetryConfig;
  signal?: AbortSignal;
};

Low-level request

const result = await client.request({
  method: 'POST',
  path: '/events',
  body: {
    type: 'user.created',
  },
  headers: {
    'x-request-id': 'req-123',
  },
  timeout: 3000,
});

Request Config

type RequestConfig = {
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
  path: string;
  query?: Record<string, string | number | boolean | null | undefined>;
  body?: unknown;
  headers?: Record<string, string>;
  timeout?: number;
  retry?: RetryConfig;
  signal?: AbortSignal;
};

Header behavior

Headers are merged in this order:

  1. default headers
  2. client headers
  3. request headers
  4. auth modifications
  5. beforeRequest hook modifications

That means request-level headers override client-level headers, and auth can still overwrite auth-related header values.

Timeout behavior

Timeout is resolved in this order:

  1. request-level timeout
  2. client-level timeout
  3. default timeout: 5000

Response parsing

Responses are parsed automatically:

  • application/json → parsed JSON
  • other content types → text
  • 204 No Contentundefined

Body behavior

If request body is an object, the client:

  • serializes it with JSON.stringify(...)
  • sets content-type: application/json only if you did not set it yourself

If request body is a string, the client:

  • sends it as-is
  • does not force a content-type