Data Adapters

Connect to data sources with client-side adapters for static data, REST APIs, and custom backends.

Data Adapters

InferaGraph is framework-agnostic and makes no assumptions about where your data lives. The DataAdapter interface defines a contract for how applications provide data to InferaGraph -- whether from a static file, a REST API, a GraphQL endpoint, or a database.

The DataAdapter Interface

Seven methods that cover the full data lifecycle: initial load, node expansion, pathfinding, search, filtering, and content retrieval. All methods are async and return Promises.

interface DataAdapter {
  // Called once on mount — return the initial visible graph
  getInitialView(config?: DataAdapterConfig): Promise<GraphData>;

  // Load a single node by ID
  getNode(id: string): Promise<Node | undefined>;

  // Expand: fetch neighbors within N hops
  getNeighbors(id: string, depth?: number): Promise<GraphData>;

  // Pathfinding between two nodes
  findPath(fromId: string, toId: string): Promise<GraphData>;

  // Full-text search with pagination
  search(query: string, page?: PageToken): Promise<SearchResult>;

  // Attribute-based filtering with pagination
  filter(filter: FilterCriteria, page?: PageToken): Promise<SearchResult>;

  // Rich content for detail panels (optional)
  getContent(id: string): Promise<NodeContent | undefined>;
}

StaticDataAdapter

For small or static datasets, the built-in StaticDataAdapter wraps an in-memory graph and implements the full DataAdapter interface. Perfect for prototyping or apps where the entire graph fits in memory.

import { StaticDataAdapter } from '@inferagraph/core';
import { GraphProvider, InferaGraph } from '@inferagraph/react';

// Wrap a static dataset — great for prototyping or small graphs
const adapter = new StaticDataAdapter({
  nodes: [
    { id: 'abraham', attributes: { name: 'Abraham', type: 'person' } },
    { id: 'sarah', attributes: { name: 'Sarah', type: 'person' } },
    { id: 'isaac', attributes: { name: 'Isaac', type: 'person' } },
  ],
  edges: [
    { id: 'e1', sourceId: 'abraham', targetId: 'isaac',
      attributes: { type: 'father_of' } },
    { id: 'e2', sourceId: 'sarah', targetId: 'isaac',
      attributes: { type: 'mother_of' } },
    { id: 'e3', sourceId: 'abraham', targetId: 'sarah',
      attributes: { type: 'husband_of' } },
  ],
});

function App() {
  return (
    <GraphProvider adapter={adapter}>
      <InferaGraph />
    </GraphProvider>
  );
}

Custom Adapter (REST API)

Implement a custom adapter to fetch data from any backend. Each method maps naturally to a REST endpoint, GraphQL query, or WebSocket message.

import type { DataAdapter } from '@inferagraph/core';
import { GraphProvider, InferaGraph } from '@inferagraph/react';

// Custom adapter: fetch from any REST API
const apiAdapter: DataAdapter = {
  getInitialView: () =>
    fetch('/api/graph').then(r => r.json()),
  getNode: (id) =>
    fetch(`/api/nodes/${id}`).then(r => r.json()),
  getNeighbors: (id, depth) =>
    fetch(`/api/graph/neighbors/${id}?depth=${depth}`).then(r => r.json()),
  findPath: (from, to) =>
    fetch(`/api/graph/path?from=${from}&to=${to}`).then(r => r.json()),
  search: (q, page) =>
    fetch(`/api/search?q=${q}&offset=${page?.offset ?? 0}`).then(r => r.json()),
  filter: (f, page) =>
    fetch('/api/filter', {
      method: 'POST',
      body: JSON.stringify({ filter: f, page }),
    }).then(r => r.json()),
  getContent: (id) =>
    fetch(`/api/content/${id}`).then(r =>
      r.ok ? r.json() : undefined
    ),
};

function App() {
  return (
    <GraphProvider adapter={apiAdapter}>
      <InferaGraph />
    </GraphProvider>
  );
}

Using GraphProvider with Adapters

GraphProvider accepts either a static data prop or a dynamic adapter prop. Both work seamlessly with InferaGraph.

import { GraphProvider, InferaGraph } from '@inferagraph/react';

// Option 1: Static data (simple)
<GraphProvider data={patriarchsGraph}>
  <InferaGraph />
</GraphProvider>

// Option 2: Dynamic adapter (REST, GraphQL, WebSocket, etc.)
<GraphProvider adapter={apiAdapter}>
  <InferaGraph />
</GraphProvider>

useInferaGraph with Adapters

When using an adapter, the useInferaGraph hook exposes additional methods for on-demand data loading. The DataManager maintains an accumulating cache -- fetched data is merged into the local GraphStore, so repeated expansions never re-fetch nodes you already have.

import { useInferaGraph, InferaGraph } from '@inferagraph/react';

function GraphExplorer() {
  const {
    expandNode,  // Fetch and merge neighbors for a node
    findPath,    // Find path between two nodes
    search,      // Full-text search via the adapter
    getContent,  // Load rich content for detail panels
    isReady,     // True once initial view is loaded
  } = useInferaGraph();

  const handleNodeClick = async (nodeId: string) => {
    // Expand neighbors — e.g., click Abraham to see Isaac, Sarah
    await expandNode(nodeId, 2);

    // Load detail content
    const content = await getContent(nodeId);
  };

  if (!isReady) return <Loading />;
  return <InferaGraph onNodeClick={handleNodeClick} />;
}