Skip to content

Eden Treaty ​

Eden Treaty is an object representation to interact with server with type safety, auto-completion, and error handling.

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

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

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

export type App = typeof app 
// server.ts
import { Elysia, t } from 'elysia'

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

export type App = typeof app 

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

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

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

// response type: 'Hi Elysia'
const { data: pong, error } = app.hi.get()
// client.ts
import { treaty } from '@elysiajs/eden'
import type { App } from './server' 

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

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

Tree like syntax ​

HTTP Path is a resource indicator for file-system tree.

File system is consists of multiple level of folders for example:

  • /documents/elysia
  • /documents/kalpas
  • /documents/kelvin

Each level is separate by / (slash) and a name.

However in JavaScript, instead of using "/" (slash) we use "." (dot) instead to access a deeper resources.

Eden Treaty turns an Elysia server into a file-system tree like system to access in JavaScript frontend instead.

PathTreaty
/.index
/hi.hi
/deep/nested.deep.nested

Combined with HTTP method, allowing us fully interact with Elysia server.

PathMethodTreaty
/GET.index.get()
/hiGET.hi.get()
/deep/nestedGET.deep.nested.get()
/deep/nestedPOST.deep.nested.post()

Dynamic path ​

However, dynamic path parameter cannot be express by using notation, if fully replaced then we don't know what the parameter name is supposed to be.

typescript
// ❌ Unclear what the value is suppose to represent?
treaty.item['skadi']
// ❌ Unclear what the value is suppose to represent?
treaty.item['skadi']

To handle this, we can specify a dynamic path using function to provide key value instead.

typescript
// ✅ Clear that value is dynamic path is 'name'
treaty.item({ name: 'Skadi' })
// ✅ Clear that value is dynamic path is 'name'
treaty.item({ name: 'Skadi' })
PathTreaty
/item.item
/item/:name.item({ name: 'Skadi' })
/item/:name/id.item({ name: 'Skadi' }).id