The Kodall TypeScript SDK (@kodall/kodall-client) provides strongly typed access to Kodall platform services, supporting entity CRUD operations, the Fetch query engine, custom workflows, file storage, and automated session management.
The SDK works across all modern JavaScript and TypeScript environments:
Install @kodall/kodall-client using your package manager of choice:
npm install @kodall/kodall-client
pnpm add @kodall/kodall-client
yarn add @kodall/kodall-client
bun add @kodall/kodall-client
Initialize the client with your backend server URL and API key:
import { KodallClient, isProblem, isValidation } from '@kodall/kodall-client'
// Initialize client
const client = new KodallClient({
baseUrl: 'https://docs-demo.kodall.io',
apiKey: 'e3097afe-1528-4fdb-a816-0d3724a8f318'
})
// Execute a query
try {
const todos = await client.fetch(`FETCH todo (key, title, is_completed)`)
if (isProblem(todos)) {
console.error('API Error:', todos.detail)
} else {
console.log('Retrieved todos:', todos)
}
} catch (error) {
console.error('Request failed:', error)
}
The KodallClient constructor accepts an optional configuration object:
import { KodallClient } from '@kodall/kodall-client'
// API Key mode (Node.js backend, microservices, CLI tools)
const client = new KodallClient({
baseUrl: 'https://docs-demo.kodall.io',
apiKey: process.env.KODALL_API_KEY
})
// Browser session mode (uses same-origin cookies and auto CSRF)
const browserClient = new KodallClient()
| Option | Type | Description |
|---|---|---|
baseUrl | string | Target server URL (e.g. https://docs-demo.kodall.io). If omitted in browsers, defaults to current origin /. |
apiKey | string | Optional secret API key for stateless authentication via X-API-Key. |
The SDK supports both stateless API Key authentication and stateful Session Cookie authentication:
import { KodallClient, isProblem } from '@kodall/kodall-client'
const client = new KodallClient({ baseUrl: 'https://docs-demo.kodall.io' })
try {
const session = await client.auth(
{ user: 'root', password: 'password123', locale: 'ro' },
{ roles: true, profiles: true }
)
if (isProblem(session)) {
console.error('Login failed:', session.detail)
} else {
console.log('Logged in as:', session.userName)
console.log('Roles:', session.roles)
}
} catch (err) {
console.error('Network error:', err)
}
const session = await client.auth({
accessToken: 'eyJhbGciOi...',
refreshToken: 'eyJhbGciOi...' // optional
})
// Fetch current session details
const session = await client.session({ roles: true, profiles: true })
// Refresh current session cookie token
await client.refreshSession()
// Switch active user profile
await client.changeUserProfile('sales_admin')
// Terminate active session
await client.logout()
For more authentication details, visit the Auth API Reference.
The client provides strongly typed methods to create, retrieve, mutate, and delete entities and their child records:
import { KodallClient, isProblem, isValidation } from '@kodall/kodall-client'
const client = new KodallClient({
baseUrl: 'https://docs-demo.kodall.io',
apiKey: 'e3097afe-1528-4fdb-a816-0d3724a8f318'
})
// Create Entity with nested children
const createRes = await client.create({
entity_name: 'todo',
properties: {
title: 'Review SDK Documentation',
is_completed: 0
},
children: {
todo_todo_item: [
{
entity_name: 'todo_item',
properties: { description: 'Read TypeScript guide', is_completed: 1 }
}
]
}
})
if (isValidation(createRes)) {
console.error('Validation error on field:', createRes.propertyName, createRes.detail)
} else if (!isProblem(createRes)) {
console.log('Entity created with key:', createRes.key)
}
// Retrieve Entity by Key
const entity = await client.get('todo', createRes.key)
console.log('Entity data:', entity)
// Update Entity
await client.update({
entity_name: 'todo',
properties: {
key: createRes.key,
title: 'Review SDK Documentation (Completed)',
is_completed: 1
}
})
// Delete Entity
await client.delete('todo', createRes.key)
For more entity operations and response structures, visit the Entities API Reference.
Execute declarative Kodall Fetch queries, parse AST trees, or inspect result metadata:
// Execute query
const rows = await client.fetch(`
FETCH todo (key, title, is_completed) {
todo_item TO id_todo (key AS item_key, description, is_completed AS item_completed)
}
FILTER AND (is_completed == 0)
ORDER BY key DESC
LIMIT 10
`)
// Parse Query AST
const ast = await client.parseQuery(`FETCH todo (key, title)`)
// Inspect Query Metadata
const metadata = await client.fetchMetadata(`FETCH todo (key, title)`)
For more query syntax options, visit the Fetch API Reference.
Invoke server-side workflows by name and method:
const result = await client.workflow('DemoWf', 'hello', {
name: 'Developer',
type: 'default'
})
console.log('Workflow response:', result)
For more workflow examples, visit the Workflow API Reference.
Upload, download, and version files with automatic multipart/form-data encoding:
// Upload a new file (File or Blob instance)
const blob = new Blob(['Hello Kodall!'], { type: 'text/plain' })
const file = new File([blob], 'greeting.txt', { type: 'text/plain' })
const uploadRes = await client.uploadFile(file)
const fileId = uploadRes[0]?.id
// Upload a new file version
const updatedBlob = new Blob(['Hello Kodall v2!'], { type: 'text/plain' })
const updatedFile = new File([updatedBlob], 'greeting.txt', { type: 'text/plain' })
await client.uploadFileVersion(updatedFile, fileId)
// Download file as Blob
const downloadedBlob = await client.getFile(fileId, undefined, 'download')
For more storage operations, visit the Storage API Reference.
The SDK provides runtime type guard functions to inspect response types without manual property checks:
import {
isProblem,
isValidation,
isOperation,
isEntity
} from '@kodall/kodall-client'
const result = await client.create(payload)
if (isValidation(result)) {
// HTTP 424: Business rule validation constraint failed
console.error('Validation error on property:', result.propertyName)
console.error('Message:', result.detail)
} else if (isProblem(result)) {
// HTTP 400/401/403/500: Standard Problem Details
console.error('API Error (' + result.status + '):', result.detail)
} else if (isOperation(result)) {
// Successful insert / update / delete operation
console.log('Operation successful. Entity key:', result.key)
}
AbortSignal)All client methods accept an optional options parameter supporting standard AbortSignal for request cancellation:
const controller = new AbortController()
// Cancel request after 5 seconds timeout
const timeoutId = setTimeout(() => controller.abort(), 5000)
try {
const result = await client.get('todo', 1, { signal: controller.signal })
clearTimeout(timeoutId)
} catch (err: any) {
if (err.name === 'AbortError') {
console.warn('Request was aborted by timeout.')
} else {
console.error('Request failed:', err)
}
}