Vanilla Client
Use the vanilla JavaScript/TypeScript client to call your API from any environment.
Installation
npm install @deessejs/clientSetup
import { createClient } from '@deessejs/client'
import { fetchTransport } from '@deessejs/client'
// Create a typed client
const client = createClient<AppRouter>({
transport: fetchTransport('/api'),
})Calling Procedures
Queries (GET Requests)
Queries use HTTP GET and accept arguments as URL query parameters:
// Simple query with primitives
const users = await client.users.list({ limit: 20, offset: 0 })
// GET /api/users.list?limit=20&offset=0Mutations (POST Requests)
Mutations use HTTP POST and send arguments as JSON body:
// Mutation with JSON body
const user = await client.users.create({ name: 'John', email: 'john@example.com' })
// POST /api/users.create with JSON bodyQuery Parameters
When calling queries, arguments are sent as URL query parameters.
Type Coercion
The server automatically coerces URL string values to their proper types:
Prop
Type
| URL Value | Coerced To |
|---|---|
"20" | 20 (number) |
"true", "1" | true (boolean) |
"false", "0" | false (boolean) |
| Other strings | string (passthrough) |
Arrays
Arrays are serialized using repeat parameter syntax:
const users = await client.users.list({ ids: [1, 2, 3] })
// GET /api/users.list?ids=1&ids=2&ids=3The server receives arrays as string arrays: { ids: ['1', '2', '3'] }.
Complex Objects
Complex nested objects cannot be serialized to URL parameters. Use a mutation with POST for complex query arguments:
// Don't - nested objects are skipped with a warning
const results = await client.users.search({
filter: { status: 'active', role: 'admin' },
})
// Do - use POST for complex queries
const results = await client.users.search({
filter: { status: 'active', role: 'admin' },
})
// POST /api/users.search with JSON bodyWhen a nested object is passed to a GET request, a warning is logged and the object is skipped.
Type Safety
The client is fully type-safe. All procedure inputs and outputs are inferred from your server router:
// TypeScript knows the exact types
const user = await client.users.get({ id: 1 })
// user is typed based on server return type
// Autocomplete works for procedure names
client.users. // VS Code suggests: get, list, create, delete, etc.Request Options
You can customize requests with options:
const user = await client.users.get({ id: 1 }, {
method: 'GET', // HTTP method (default varies by procedure type)
headers: { // Custom headers
'Authorization': 'Bearer token',
},
})Error Handling
The client returns a result object with ok boolean:
const result = await client.users.get({ id: 999 })
if (result.ok) {
console.log(result.value) // Typed user object
} else {
console.error(result.error) // Error details
}Next Steps
- React Hooks - Use the client with React
- Query Options - Configure query behavior
- Mutations - Define write operations