ObjectQL Data Source Adapter for Object UI - Seamlessly connect your Object UI components with ObjectQL API backends using the official @objectql/sdk.
- ✅ Official SDK Integration - Built on top of @objectql/sdk for reliable API communication
- ✅ Universal DataSource Interface - Implements the standard Object UI data source protocol
- ✅ Full TypeScript Support - Complete type definitions and IntelliSense
- ✅ React Hooks - Easy-to-use hooks for data fetching and mutations
- ✅ Automatic Query Conversion - Converts universal query params to ObjectQL format
- ✅ Error Handling - Robust error handling with typed error responses
- ✅ Authentication - Built-in support for token-based authentication
- ✅ Universal Runtime - Works in browsers, Node.js, and edge runtimes
# Using npm
npm install @object-ui/data-objectql @objectql/sdk
# Using yarn
yarn add @object-ui/data-objectql @objectql/sdk
# Using pnpm
pnpm add @object-ui/data-objectql @objectql/sdkNote: The package now depends on @objectql/sdk and @objectql/types, which provide the underlying HTTP client and type definitions.
import { ObjectQLDataSource } from '@object-ui/data-objectql';
// Create a data source instance
const dataSource = new ObjectQLDataSource({
baseUrl: 'https://api.example.com',
token: 'your-auth-token'
});
// Fetch data
const result = await dataSource.find('contacts', {
$filter: { status: 'active' },
$orderby: { created: 'desc' },
$top: 10
});
console.log(result.data); // Array of contactsimport { SchemaRenderer } from '@object-ui/react';
import { ObjectQLDataSource } from '@object-ui/data-objectql';
const dataSource = new ObjectQLDataSource({
baseUrl: 'https://api.example.com',
token: authToken
});
const schema = {
type: 'data-table',
api: 'contacts',
columns: [
{ name: 'name', label: 'Name' },
{ name: 'email', label: 'Email' },
{ name: 'status', label: 'Status' }
]
};
function App() {
return <SchemaRenderer schema={schema} dataSource={dataSource} />;
}import { useObjectQL, useObjectQLQuery, useObjectQLMutation } from '@object-ui/data-objectql';
function ContactList() {
// Create data source
const dataSource = useObjectQL({
config: {
baseUrl: 'https://api.example.com',
token: authToken
}
});
// Query data
const { data, loading, error, refetch } = useObjectQLQuery(
dataSource,
'contacts',
{
$filter: { status: 'active' },
$orderby: { created: 'desc' },
$top: 20
}
);
// Mutations
const { create, update, remove } = useObjectQLMutation(
dataSource,
'contacts'
);
const handleCreate = async () => {
await create({
name: 'John Doe',
email: 'john@example.com'
});
refetch(); // Refresh the list
};
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<button onClick={handleCreate}>Add Contact</button>
<ul>
{data?.map(contact => (
<li key={contact._id}>{contact.name}</li>
))}
</ul>
</div>
);
}new ObjectQLDataSource(config: ObjectQLConfig)interface ObjectQLConfig {
baseUrl: string; // ObjectQL API base URL
token?: string; // Authentication token
headers?: Record<string, string>; // Additional headers
timeout?: number; // Request timeout (default: 30000ms)
}Note: This configuration is compatible with @objectql/sdk's DataApiClientConfig. Additional options supported by the SDK can also be passed.
Fetch multiple records.
await dataSource.find('contacts', {
$select: ['name', 'email', 'account.name'],
$filter: { status: 'active' },
$orderby: { created: 'desc' },
$skip: 0,
$top: 10,
$count: true
});Fetch a single record by ID.
const contact = await dataSource.findOne('contacts', '123', {
$select: ['name', 'email', 'phone']
});Create a new record.
const newContact = await dataSource.create('contacts', {
name: 'John Doe',
email: 'john@example.com',
status: 'active'
});Update an existing record.
const updated = await dataSource.update('contacts', '123', {
status: 'inactive'
});Delete a record.
await dataSource.delete('contacts', '123');Execute bulk operations.
const results = await dataSource.bulk('contacts', 'create', [
{ name: 'Contact 1', email: 'contact1@example.com' },
{ name: 'Contact 2', email: 'contact2@example.com' }
]);Create and manage an ObjectQL data source instance.
const dataSource = useObjectQL({
config: {
baseUrl: 'https://api.example.com',
token: authToken
}
});Fetch data with automatic loading and error states.
const { data, loading, error, refetch, result } = useObjectQLQuery(
dataSource,
'contacts',
{
$filter: { status: 'active' },
enabled: true, // Auto-fetch on mount (default: true)
refetchInterval: 5000, // Refetch every 5 seconds
onSuccess: (data) => console.log('Data loaded:', data),
onError: (error) => console.error('Error:', error)
}
);Perform create, update, delete operations.
const { create, update, remove, loading, error } = useObjectQLMutation(
dataSource,
'contacts',
{
onSuccess: (data) => console.log('Success:', data),
onError: (error) => console.error('Error:', error)
}
);
// Use the mutation functions
await create({ name: 'New Contact' });
await update('123', { name: 'Updated Name' });
await remove('123');Object UI uses universal query parameters that are automatically converted to ObjectQL format:
| Universal Param | ObjectQL Param | Example |
|---|---|---|
$select |
fields |
['name', 'email'] |
$filter |
filters |
{ status: 'active' } |
$orderby |
sort |
{ created: -1 } |
$skip |
skip |
0 |
$top |
limit |
10 |
$count |
count |
true |
const dataSource = new ObjectQLDataSource({
baseUrl: 'https://api.example.com',
token: authToken,
headers: {
'X-Custom-Header': 'value',
'X-Tenant-ID': 'tenant123'
}
});const dataSource = new ObjectQLDataSource({
baseUrl: 'https://api.example.com',
token: authToken,
spaceId: 'workspace123' // Automatically added to requests
});const result = await dataSource.find('contacts', {
$filter: {
name: { $regex: '^John' },
age: { $gte: 18, $lte: 65 },
status: { $in: ['active', 'pending'] },
'account.type': 'enterprise'
}
});const result = await dataSource.find('contacts', {
$select: [
'name',
'email',
'account.name', // Related object field
'account.industry', // Related object field
'tasks.name', // Related list field
'tasks.status' // Related list field
]
});import type { APIError } from '@object-ui/types/data';
try {
const result = await dataSource.find('contacts', params);
} catch (err) {
const error = err as APIError;
console.error('Error:', error.message);
console.error('Status:', error.status);
console.error('Code:', error.code);
console.error('Validation errors:', error.errors);
}Full TypeScript support with generics:
interface Contact {
_id: string;
name: string;
email: string;
status: 'active' | 'inactive';
created: Date;
}
const dataSource = new ObjectQLDataSource<Contact>({
baseUrl: 'https://api.example.com'
});
// Fully typed results
const result = await dataSource.find('contacts');
const contact: Contact = result.data[0]; // Typed!This adapter is built on top of the official ObjectQL SDK:
Object UI Components
↓
@object-ui/data-objectql (this package)
↓
@objectql/sdk (DataApiClient)
↓
ObjectQL Server API
- Reliability: Uses the official, well-tested ObjectQL HTTP client
- Compatibility: Always compatible with the latest ObjectQL server versions
- Type Safety: Leverages @objectql/types for consistent type definitions
- Universal Runtime: Works in browsers, Node.js, Deno, and edge runtimes
- Automatic Updates: SDK improvements automatically benefit this adapter
If you're upgrading from a previous version that used custom fetch logic:
-
Update your dependencies to include
@objectql/sdk:pnpm add @objectql/sdk @objectql/types
-
The configuration interface has been simplified. Remove deprecated options:
version- The SDK handles API versioning internallyspaceId- Use custom headers if neededwithCredentials- The SDK manages this automatically
-
Filter formats now support both object and array notation:
// Object format (converted to array internally) $filter: { status: 'active', age: 18 } // Array format (FilterExpression - native ObjectQL format) $filter: [['status', '=', 'active'], ['age', '=', 18]]
MIT