FLXBL SDK
Type-safe client for your FLXBL instance. Zero dependencies, native fetch, works in Node.js 18+, Deno, Bun, and edge runtimes.
Installation
npm install @flxbl-dev/clientQuick Start
import { FlxblClient } from '@flxbl-dev/client';
const client = new FlxblClient({
instanceUrl: 'https://api.flxbl.dev',
apiKey: 'flxbl_your_api_key',
});
// Create a record
const product = await client.request('POST', '/api/v1/dynamic/Product', {
name: 'Wireless Headphones',
price: 299.99,
inStock: true,
});
console.log(product); // { id: 'node_abc123', name: '...', ... }Authentication
The SDK supports two authentication methods. Use API keys for server-side applications and access tokens (JWTs) for client-side or per-user sessions.
import { FlxblClient } from '@flxbl-dev/client';
// Option 1: API key (recommended for server-side)
const client = new FlxblClient({
instanceUrl: 'https://api.flxbl.dev',
apiKey: 'flxbl_your_api_key',
});
// Option 2: Access token (for client-side / user sessions)
const client2 = new FlxblClient({
instanceUrl: 'https://api.flxbl.dev',
accessToken: 'eyJhbGciOiJIUzI1NiIs...',
});
// You can also set or update the token dynamically
client2.setAccessToken('new_jwt_token_here');Collections
The generated client (from flxbl generate) provides typed collection accessors
with full CRUD operations. Each collection is typed as
createCollection<T, TCreate, TUpdate>() with methods:
| Method | Description |
|---|---|
findMany(options?) | Query records with filters, sorting, pagination, and traversals |
findById(id) | Get a single record by ID |
create(data) | Create a new record |
update(id, data) | Partial update of a record |
delete(id) | Delete a record by ID |
// With the generated typed client (from `flxbl generate`):
import { createFlxblClient } from './flxbl/_generated';
const client = createFlxblClient({
instanceUrl: 'https://api.flxbl.dev',
apiKey: 'flxbl_your_api_key',
});
// Typed CRUD operations
const products = await client.Product.findMany({
where: { inStock: { $eq: true } },
orderBy: 'price',
orderDirection: 'DESC',
limit: 20,
});
const product = await client.Product.findById('node_abc123');
const newProduct = await client.Product.create({
name: 'New Widget',
price: 49.99,
inStock: true,
});
const updated = await client.Product.update('node_abc123', {
price: 39.99,
});
await client.Product.delete('node_abc123');Query Options
The findMany method accepts a QueryOptions<T> object
with the following fields:
| Field | Type | Description |
|---|---|---|
where | object | Filter conditions using query operators |
select | string[] | Fields to include in the response |
orderBy | string | Field name to sort by |
orderDirection | 'ASC' | 'DESC' | Sort direction |
offset | number | Number of items to skip |
limit | number | Maximum items to return |
includeCount | boolean | Include total count in response |
traverse | object[] | Relationship traversals (relationship, direction, select, where) |
const results = await client.Product.findMany({
// Filter conditions
where: {
price: { $lte: 100 },
inStock: { $eq: true },
tags: { $contains: 'electronics' },
},
// Field selection
select: ['name', 'price', 'description'],
// Sorting
orderBy: 'price',
orderDirection: 'ASC',
// Pagination
offset: 0,
limit: 20,
includeCount: true,
// Graph traversal
traverse: [
{
relationship: 'BELONGS_TO',
direction: 'out',
select: ['name', 'slug'],
},
],
});
console.log(results.items); // Product[]
console.log(results.count); // Total matching countFilter Operators
Use these operators in where conditions:
| Operator | Description | Example |
|---|---|---|
$eq | Equal | { status: { $eq: 'active' } } |
$neq | Not equal | { status: { $neq: 'archived' } } |
$gt | Greater than | { price: { $gt: 100 } } |
$gte | Greater than or equal | { price: { $gte: 100 } } |
$lt | Less than | { price: { $lt: 50 } } |
$lte | Less than or equal | { price: { $lte: 50 } } |
$in | In array | { status: { $in: ['a', 'b'] } } |
$notIn | Not in array | { status: { $notIn: ['x'] } } |
$isNull | Is null | { deletedAt: { $isNull: true } } |
$contains | String contains | { name: { $contains: 'phone' } } |
$startsWith | String starts with | { name: { $startsWith: 'Pro' } } |
$endsWith | String ends with | { email: { $endsWith: '.com' } } |
$and | Logical AND | Combine multiple conditions |
$or | Logical OR | Match any condition |
Vector Search
Search entities by vector similarity using client.vectorSearch().
This requires a VECTOR field on the target entity.
// Semantic search using vector embeddings
const results = await client.vectorSearch<Product>('Product', {
field: 'embedding',
vector: [0.1, 0.2, 0.3, /* ...1536 dimensions */],
topK: 5,
where: { isActive: { $eq: true } },
select: ['name', 'price', 'description'],
});
for (const result of results) {
console.log(result.data.name); // Product name
console.log(result.score); // Cosine similarity (0-1)
}
Option Type Description field string Name of the VECTOR field (required) vector number[] Query vector — must match the field's dimensions (required) topK number Max results, 1–100 (default: 10) where object Optional filter conditions select string[] Optional fields to include
GraphQL
Execute raw GraphQL queries against your tenant's GraphQL endpoint:
// Execute raw GraphQL queries
const tenantId = 'your_tenant_id';
const result = await client.graphql<{
products: Array<{ id: string; name: string; price: number }>;
}>(tenantId, `
query {
products(where: { inStock: { equals: true } }, limit: 10) {
id
name
price
}
}
`);
console.log(result.data?.products);
Relationships
Manage graph relationships between entities using client.relationships():
// Manage relationships between entities
const rel = client.relationships('Product', 'node_abc123');
// Create a relationship
await rel.create('BELONGS_TO', 'node_category_xyz', {
addedAt: new Date().toISOString(),
});
// List relationships
const related = await rel.list('BELONGS_TO', 'out');
console.log(related.items);
// Delete a relationship
await rel.delete('BELONGS_TO', 'node_category_xyz');
Error Handling
The SDK throws typed errors for different failure scenarios. All errors extend
FlxblApiError:
Error Class Status When FlxblValidationError 400 Invalid input — includes field-level validationErrors FlxblAuthError 401 Missing or invalid credentials FlxblNotFoundError 404 Entity or record not found FlxblApiError * Any other API error (403, 429, 500, etc.)
import {
FlxblApiError,
FlxblAuthError,
FlxblValidationError,
FlxblNotFoundError,
} from '@flxbl-dev/client';
try {
await client.Product.create({ name: '' });
} catch (error) {
if (error instanceof FlxblValidationError) {
// 400 — field-level validation errors
console.log(error.validationErrors);
// [{ field: 'name', message: 'Name is required' }]
} else if (error instanceof FlxblAuthError) {
// 401 — invalid or missing credentials
console.log(error.message);
} else if (error instanceof FlxblNotFoundError) {
// 404 — entity or record not found
console.log(error.message);
} else if (error instanceof FlxblApiError) {
// Other API errors (403, 429, 500, etc.)
console.log(error.statusCode, error.message);
}
}
Code Generation
The SDK works best with a generated typed client. Use the FLXBL CLI
to generate TypeScript interfaces and a typed client factory from your active schema:
# Generate a typed client
npm install -g @flxbl-dev/cli
flxbl generate
The generated client includes entity types, create/update input types, query option helpers,
and a createFlxblClient() factory with typed collection accessors for every entity
in your schema.
Next Steps
- CLI - Generate typed clients, manage schemas, and query data
- API Reference - Complete REST and GraphQL documentation
- Query DSL - Deep dive into filter operators and traversals
- Schema Design - Define entities, fields, and relationships