Skip to content

HeliosDB GraphQL Interface

HeliosDB GraphQL Interface

A comprehensive GraphQL API layer for HeliosDB v3.0 with automatic schema generation, real-time subscriptions, and federation support.

Features

  • Automatic Schema Generation: Generate GraphQL schemas from SQL table definitions
  • CRUD Operations: Full Create, Read, Update, Delete support via GraphQL mutations
  • Real-time Subscriptions: WebSocket-based subscriptions with CDC integration
  • Advanced Filtering: Complex where clauses with AND/OR/NOT operators
  • Sorting & Pagination: Cursor-based and offset-based pagination
  • GraphQL Playground: Interactive API explorer for development
  • Federation Support: Apollo Federation for microservices architecture
  • Type Safety: Strongly-typed GraphQL schema with proper SQL type mappings
  • Authentication: JWT-based authentication and role-based access control
  • Rate Limiting: Configurable rate limiting per IP address
  • Query Complexity: Protection against expensive queries

Quick Start

Basic Server

use heliosdb_graphql::{GraphQLServer, GraphQLConfigBuilder};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = GraphQLConfigBuilder::new()
.bind_address("0.0.0.0:8080".parse()?)
.playground(true)
.introspection(true)
.subscriptions(true)
.build();
let server = GraphQLServer::new(config).await?;
server.run().await?.wait().await?;
Ok(())
}

Schema Generation

Given a SQL table:

CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);

The following GraphQL schema is auto-generated:

type User {
id: ID!
name: String!
email: String!
createdAt: DateTime!
}
type Query {
user(id: ID!): User
users(
where: UserWhereInput
orderBy: [UserOrderByInput!]
skip: Int
take: Int
): [User!]!
usersCount(where: UserWhereInput): Int!
}
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(id: ID!, data: UserUpdateInput!): User
deleteUser(id: ID!): User
}
type Subscription {
userCreated: User!
userUpdated: User!
userDeleted: User!
}

Queries

Find by ID

query {
user(id: "1") {
id
name
email
}
}

List with Filtering

query {
users(
where: {
AND: [
{ name: { contains: "John" } }
{ email: { endsWith: "@example.com" } }
]
}
orderBy: [{ createdAt: DESC }]
take: 10
skip: 0
) {
id
name
email
createdAt
}
}

Count

query {
usersCount(where: { name: { contains: "John" } })
}

Mutations

Create

mutation {
createUser(data: {
name: "John Doe"
email: "john@example.com"
}) {
id
name
email
}
}

Update

mutation {
updateUser(
id: "1"
data: { name: "Jane Doe" }
) {
id
name
email
}
}

Delete

mutation {
deleteUser(id: "1") {
id
name
}
}

Subscriptions

Real-time Updates

subscription {
userCreated {
id
name
email
}
}
subscription {
userUpdated {
id
name
email
}
}
subscription {
userDeleted {
id
}
}

Filtering

String Filters

input StringFilter {
equals: String
not: String
in: [String!]
notIn: [String!]
contains: String
startsWith: String
endsWith: String
mode: QueryMode # DEFAULT or INSENSITIVE
}

Numeric Filters

input IntFilter {
equals: Int
not: Int
in: [Int!]
notIn: [Int!]
lt: Int
lte: Int
gt: Int
gte: Int
}

DateTime Filters

input DateTimeFilter {
equals: DateTime
not: DateTime
in: [DateTime!]
notIn: [DateTime!]
lt: DateTime
lte: DateTime
gt: DateTime
gte: DateTime
}

Logical Operators

input UserWhereInput {
name: StringFilter
email: StringFilter
AND: [UserWhereInput!]
OR: [UserWhereInput!]
NOT: UserWhereInput
}

Pagination

Offset-based

query {
users(skip: 0, take: 10) {
id
name
}
}

Cursor-based (Relay)

query {
usersConnection(first: 10, after: "cursor123") {
edges {
cursor
node {
id
name
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}

Authentication

JWT Authentication

use heliosdb_graphql::auth::{TokenManager, Claims};
let manager = TokenManager::new("secret".to_string());
let claims = Claims::new("user123".to_string(), vec!["admin".to_string()], 3600);
let token = manager.generate_token(claims)?;

Authorization Header

Authorization: Bearer <jwt-token>

Federation

Entity Resolution

use heliosdb_graphql::federation::{FederationSupport, TableEntityResolver};
let federation = FederationSupport::new();
let resolver = Arc::new(TableEntityResolver::new("users".to_string()));
federation.register_resolver("User".to_string(), resolver).await;

Federation Schema

extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key"])
type User @key(fields: "id") {
id: ID!
name: String!
email: String!
}

Configuration

use heliosdb_graphql::GraphQLConfigBuilder;
use std::time::Duration;
let config = GraphQLConfigBuilder::new()
.bind_address("0.0.0.0:8080".parse()?)
.playground(true)
.introspection(true)
.max_depth(10)
.max_complexity(100)
.subscriptions(true)
.federation(false)
.request_timeout(Duration::from_secs(30))
.rate_limit(1000) // requests per minute
.jwt_secret("your-secret".to_string())
.log_queries(true)
.build();

Type Mappings

SQL TypeGraphQL Type
VARCHAR, TEXTString
INTEGER, SERIALInt
BIGINTString (to avoid precision loss)
FLOAT, DOUBLEFloat
NUMERIC, DECIMALDecimal
BOOLEANBoolean
UUIDUUID
JSON, JSONBJSON
TIMESTAMP, DATEDateTime
BYTEA, BLOBBytes

Examples

See the examples/ directory for complete examples:

  • basic_server.rs - Basic GraphQL server setup
  • subscription_example.rs - Real-time subscriptions with CDC

Testing

Terminal window
cargo test -p heliosdb-graphql

Integration with HeliosDB

The GraphQL interface integrates with:

  • heliosdb-metadata: Table schema introspection
  • heliosdb-compute: Query execution engine
  • heliosdb-storage: Data access layer
  • heliosdb-cdc: Change data capture for subscriptions

Performance

  • Query caching with LRU cache
  • DataLoader pattern for batch loading
  • Query complexity analysis
  • Rate limiting per IP
  • Connection pooling

License

Apache-2.0