Eden Treaty Legacy - ElysiaJS | ElysiaJS

ID: 2138https://elysiajs.com/eden/treaty/legacy.html
Source

Eden Treaty Legacy

NOTE
This is a documentation for Eden Treaty 1 (edenTreaty).
For a new project, we recommend starting with Eden Treaty 2 (treaty) instead.

Eden Treaty is an object‑like representation of an Elysia server.
It provides accessor methods like a normal object with type information directly from the server, helping us move faster and ensuring nothing breaks.


Getting Started

To use Eden Treaty, first export your existing Elysia server type:

// server.ts
import { Elysia, t } from 'elysia'

const app = new Elysia()
    .get('/', () => 'Hi Elysia')
    .get('/id/:id', ({ params: { id } }) => id)
    .post('/mirror', ({ body }) => body, {
        body: t.Object({
            id: t.Number(),
            name: t.String()
        })
    })
    .listen(3000)

export type App = typeof app

Then import the server type, and consume the Elysia API on the client:

// client.ts
import { edenTreaty } from '@elysiajs/eden'
import type { App } from './server'

const app = edenTreaty<App>('http://localhost:')


// response type: 'Hi Elysia'
const { data: pong, error } = app.get()

// response type: 1895
const { data: id, error } = app.id['1895'].get()

// response type: { id: 1895, name: 'Skadi' }
const { data: nendoroid, error } = app.mirror.post({
    id: 1895,
    name: 'Skadi'
})

TIP
Eden Treaty is fully type‑safe with auto‑completion support.

Anatomy

Eden Treaty will transform all existing paths to an object‑like representation, that can be described as:

EdenTreaty.<1>.<2>.n.<method>({ ... })

Path

Eden will transform / into . which can be called with a registered method, for example:

  • /path.path
  • /nested/path.nested.path

Path parameters

Path parameters will be mapped automatically by their name in the URL.

  • /id/:id.id.<anyThing>
    • e.g., .id.hi
    • e.g., .id['123']

TIP
If a path doesn’t support path parameters, TypeScript will show an error.

Query

You can append queries to a path with $query:

app.get({
    $query: {
        name: 'Eden',
        code: 'Gold'
    }
})

Fetch

Eden Treaty is a fetch wrapper; you can pass any valid Fetch parameters using $fetch:

app.post({
    $fetch: {
        headers: {
            'x-organization': 'MANTIS'
        }
    }
})

Error Handling

Eden Treaty will return a value of data and error as a result, both fully typed.

// response type: { id: 1895, name: 'Skadi' }
const { data: nendoroid, error } = app.mirror.post({
    id: 1895,
    name: 'Skadi'
})

if (error) {
    switch (error.status) {
        case 400:
        case 401:
            warnUser(error.value)
            break

        case 500:
        case 502:
            emergencyCallDev(error.value)
            break

        default:
            reportError(error.value)
            break
    }

    throw error
}

const { id, name } = nendoroid

Both data and error will be typed as nullable until you confirm their status with a type guard.
In simple terms: if the fetch is successful, data has a value and error is null, and vice‑versa.

TIP
Error is wrapped with an Error and its value can be retrieved from Error.value.

Error type based on status

Both Eden Treaty and Eden Fetch can narrow down an error type based on status code if you explicitly provide an error type in the Elysia server.

// server.ts
import { Elysia, t } from 'elysia'

const app = new Elysia()
    .model({
        nendoroid: t.Object({
            id: t.Number(),
            name: t.String()
        }),
        error: t.Object({
            message: t.String()
        })
    })
    .get('/', () => 'Hi Elysia')
    .get('/id/:id', ({ params: { id } }) => id)
    .post('/mirror', ({ body }) => body, {
        body: 'nendoroid',
        response: {
            200: 'nendoroid',
            400: 'error',
            401: 'error'
        }
    })
    .listen(3000)

export type App = typeof app

On the client side:

// client.ts
import { edenTreaty } from '@elysiajs/eden'
import type { App } from './server'

const app = edenTreaty<App>('http://localhost:')

// Example of handling typed errors based on status code
const { data: nendoroid, error } = app.mirror.post({
    id: 1895,
    name: 'Skadi'
})