Config
Eden Treaty accepts 2 parameters:
- urlOrInstance - URL endpoint or Elysia instance
- options (optional) - Customize fetch behavior
urlOrInstance
Section titled “urlOrInstance”Accepts either a URL endpoint as a string or a literal Elysia instance.
Eden will change the behavior based on the type as follows:
URL endpoint (string)
Section titled “URL endpoint (string)”If a URL endpoint is passed, Eden Treaty will use fetch or config.fetcher to create a network request to an Elysia instance.
import { treaty } from '@elysia/eden'import type { App } from './server'
const api = treaty<App>('localhost:3000')You may or may not specify a protocol for the URL endpoint.
Eden Treaty will prepend a protocol automatically as follows:
- If a protocol is specified, use the URL directly
- If the URL identifies localhost or a supported local address, use http
- Otherwise, use https
This also applies to WebSocket for choosing between ws:// and wss://.
Elysia instance
Section titled “Elysia instance”If an Elysia instance is passed, Eden Treaty will create a Request class and pass it to Elysia.handle directly without creating a network request.
This allows us to interact with the Elysia server directly without request overhead, or the need to start a server.
import { Elysia } from 'elysia'import { treaty } from '@elysia/eden'
const app = new Elysia() .get('/hi', 'Hi Elysia')
const api = treaty(app)If an instance is passed, a generic is not needed as Eden Treaty can infer the type from the parameter directly.
This pattern is recommended for performing unit tests, or creating a type-safe reverse proxy server or microservices.
Options
Section titled “Options”The optional 2nd parameter lets Eden Treaty customize fetch behavior, accepting parameters as follows:
- fetch - add default parameters to fetch initialization (RequestInit)
- fetcher - custom function with the same interface as
fetch - headers - define default headers
- onRequest - intercept and modify the fetch request before firing
- onResponse - intercept and modify fetch’s response
- parseDate - automatically parse a date string to a Date object
- throwHttpError - automatically throw an error if the response status is not ok (2xx)
Set default RequestInit options such as credentials or caching. Set headers through headers; the current config type excludes headers and method from fetch. The following examples assume treaty and your exported App type are imported.
import { treaty } from '@elysia/eden'import type { App } from './server'
treaty<App>('localhost:3000', { fetch: { credentials: 'include' }})All parameters that are passed to fetch will be passed to the fetcher, which is equivalent to:
fetch('http://localhost:3000', { credentials: 'include'})Fetcher
Section titled “Fetcher”Provide a custom fetcher function instead of using an environment’s default fetch.
treaty<App>('localhost:3000', { fetcher(url, options) { return fetch(url, options) }})A custom fetcher must accept the same arguments as fetch and return a Web Standard Response. Clients such as Axios need an adapter; they cannot be passed directly.
Headers
Section titled “Headers”Provide default request headers with options.headers.
treaty<App>('localhost:3000', { headers: { 'X-Custom': 'Griseo' }})All parameters that are passed to fetch will be passed to the fetcher, which is equivalent to:
fetch('http://localhost:3000', { headers: { 'X-Custom': 'Griseo' }})Headers may accept the following as parameters:
- Object
- Function
Headers object
Section titled “Headers object”If an object is passed, then it will be passed to fetch directly.
treaty<App>('localhost:3000', { headers: { 'X-Custom': 'Griseo' }})Function
Section titled “Function”You may specify headers as a function to return custom headers based on conditions.
treaty<App>('localhost:3000', { headers(path, options) { if(path.startsWith('/user')) return { authorization: 'Bearer 12345' } }})You may return an object to append its value to fetch headers.
The headers function accepts 2 parameters:
- path
string- path which will be sent to the parameter- note: hostname will be excluded, e.g., (/user/griseo)
- options
RequestInit: Parameters passed through the 2nd parameter of fetch
You may define a headers function as an array if multiple conditions are needed.
treaty<App>('localhost:3000', { headers: [ (path, options) => { if(path.startsWith('/user')) return { authorization: 'Bearer 12345' } } ]})Eden Treaty will run all functions even if the value is already returned.
Headers priority
Section titled “Headers priority”Eden Treaty will prioritize duplicate headers as follows:
- Inline method - Passed in method function directly
- headers - Passed in
config.headers
- If
config.headersis an array, parameters that come after will be prioritized
For example:
const api = treaty<App>('localhost:3000', { headers: { authorization: 'Bearer Aponia' }})
api.profile.get({ headers: { authorization: 'Bearer Griseo' }})This will result in:
fetch('http://localhost:3000', { headers: { authorization: 'Bearer Griseo' }})If the inline function doesn’t specify headers, then the result will be “Bearer Aponia” instead.
onRequest
Section titled “onRequest”Intercept and modify the fetch request before firing.
You may return an object to append the value to RequestInit.
treaty<App>('localhost:3000', { onRequest(path, options) { if(path.startsWith('/user')) return { headers: { authorization: 'Bearer 12345' } } }})If a value is returned, Eden Treaty will shallow merge it into the current RequestInit, merging its headers with the existing headers.
onRequest accepts 2 parameters:
- path
string- path which will be sent to the parameter- note: hostname will be excluded, e.g., (/user/griseo)
- options
RequestInit: Parameters passed through the 2nd parameter of fetch
You may define an onRequest function as an array if multiple conditions are needed.
treaty<App>('localhost:3000', { onRequest: [ (path, options) => { if(path.startsWith('/user')) return { headers: { authorization: 'Bearer 12345' } } } ]})Eden Treaty will run all functions even if the value is already returned.
onResponse
Section titled “onResponse”Intercept fetch’s response. The first non-null return value becomes data.
treaty<App>('localhost:3000', { onResponse(response) { if(response.ok && response.headers.get('content-type')?.includes('application/json')) return response.json() }})onResponse accepts 1 parameter:
- response
Response- Web Standard Response normally returned fromfetch
You may define an onResponse function as an array if multiple conditions are needed.
treaty<App>('localhost:3000', { onResponse: [ (response) => { if(response.ok && response.headers.get('content-type')?.includes('application/json')) return response.json() } ]})Unlike headers and onRequest, Eden Treaty will loop through functions until a returned value is found or an error is thrown. The first non-null return value becomes data.
parseDate
Section titled “parseDate”- default:
true
Automatically parse a date string to a Date object.
treaty<App>('localhost:3000', { parseDate: true})throwHttpError
Section titled “throwHttpError”- default:
false
Automatically throw an error if the response status is not ok (2xx).
treaty<App>('localhost:3000', { throwHttpError: true})By default, Eden will not throw an error and will return { error } instead if the response status is not ok (2xx).
You can also supply a predicate receiving an EdenFetchError:
treaty<App>('localhost:3000', { throwHttpError: (error) => { return error.status === 418 }})If throwHttpError returns true, Eden will throw an error. Otherwise, it will return { error } instead.