Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

@object-ui/data-objectql

ObjectQL Data Source Adapter for Object UI - Seamlessly connect your Object UI components with ObjectQL API backends using the official @objectql/sdk.

Features

  • 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

Installation

# 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/sdk

Note: The package now depends on @objectql/sdk and @objectql/types, which provide the underlying HTTP client and type definitions.

Quick Start

Basic Usage

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 contacts

With React Components

import { 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} />;
}

Using React Hooks

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>
  );
}

API Reference

ObjectQLDataSource

Constructor

new ObjectQLDataSource(config: ObjectQLConfig)

Configuration Options

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.

Methods

find(resource, params)

Fetch multiple records.

await dataSource.find('contacts', {
  $select: ['name', 'email', 'account.name'],
  $filter: { status: 'active' },
  $orderby: { created: 'desc' },
  $skip: 0,
  $top: 10,
  $count: true
});
findOne(resource, id, params)

Fetch a single record by ID.

const contact = await dataSource.findOne('contacts', '123', {
  $select: ['name', 'email', 'phone']
});
create(resource, data)

Create a new record.

const newContact = await dataSource.create('contacts', {
  name: 'John Doe',
  email: 'john@example.com',
  status: 'active'
});
update(resource, id, data)

Update an existing record.

const updated = await dataSource.update('contacts', '123', {
  status: 'inactive'
});
delete(resource, id)

Delete a record.

await dataSource.delete('contacts', '123');
bulk(resource, operation, data)

Execute bulk operations.

const results = await dataSource.bulk('contacts', 'create', [
  { name: 'Contact 1', email: 'contact1@example.com' },
  { name: 'Contact 2', email: 'contact2@example.com' }
]);

React Hooks

useObjectQL(options)

Create and manage an ObjectQL data source instance.

const dataSource = useObjectQL({
  config: {
    baseUrl: 'https://api.example.com',
    token: authToken
  }
});

useObjectQLQuery(dataSource, resource, options)

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)
  }
);

useObjectQLMutation(dataSource, resource, options)

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');

Query Parameter Mapping

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

Advanced Usage

Custom Headers

const dataSource = new ObjectQLDataSource({
  baseUrl: 'https://api.example.com',
  token: authToken,
  headers: {
    'X-Custom-Header': 'value',
    'X-Tenant-ID': 'tenant123'
  }
});

Multi-tenant Support

const dataSource = new ObjectQLDataSource({
  baseUrl: 'https://api.example.com',
  token: authToken,
  spaceId: 'workspace123' // Automatically added to requests
});

Complex Filters

const result = await dataSource.find('contacts', {
  $filter: {
    name: { $regex: '^John' },
    age: { $gte: 18, $lte: 65 },
    status: { $in: ['active', 'pending'] },
    'account.type': 'enterprise'
  }
});

Field Selection with Relations

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
  ]
});

Error Handling

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);
}

TypeScript Support

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!

Architecture

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

Benefits of Using the Official SDK

  • 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

Migration from Previous Versions

If you're upgrading from a previous version that used custom fetch logic:

  1. Update your dependencies to include @objectql/sdk:

    pnpm add @objectql/sdk @objectql/types
  2. The configuration interface has been simplified. Remove deprecated options:

    • version - The SDK handles API versioning internally
    • spaceId - Use custom headers if needed
    • withCredentials - The SDK manages this automatically
  3. 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]]

License

MIT

Links