Skip to content
/ RQL Public

RQL is a lightweight alternative to GraphQL designed for modern applications and AI agents

License

Notifications You must be signed in to change notification settings

Okiynai/RQL

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RQL-Kit

A Declarative, Discoverable, and AI-Native API Protocol for TypeScript

RQL (Resource Query Language) is a lightweight alternative to GraphQL designed for modern applications and AI agents. Define your API contracts once, get automatic schema discovery, type-safe resolvers, and efficient relation batching.

Features

  • 🎯 Contract-Driven - Define what data can be fetched, not how
  • πŸ€– AI-Native - Self-documenting schemas for LLM tool use
  • πŸ”’ Secure by Default - Only exposed fields can be queried
  • ⚑ Batched Relations - Automatic N+1 prevention
  • πŸ“¦ Minimal Dependencies - Just Zod for validation
  • πŸ”§ Framework Agnostic - Core engine works anywhere

Installation

# Using bun
bun add @rql-kit/core @rql-kit/express zod

# Using npm
npm install @rql-kit/core @rql-kit/express zod

Quick Start

1. Define a Contract

// contracts/products.ts
import { defineContract } from '@rql-kit/core';
import { z } from 'zod';

export const getProductContract = defineContract({
  name: 'getProduct',
  description: 'Fetches a product by ID',
  type: 'GET',
  
  params: z.object({
    productId: z.string(),
  }),
  
  selectable: {
    id: { type: 'string', description: 'Product ID' },
    name: { type: 'string', description: 'Product name' },
    price: { type: 'number', description: 'Price in cents' },
  },
  
  async resolve({ params }) {
    // Your data fetching logic
    return { id: params.productId, name: 'Laptop', price: 99900 };
  },
});

2. Create Express Server

// server.ts
import express from 'express';
import { createRQLMiddleware } from '@rql-kit/express';
import { getProductContract } from './contracts/products';

const app = express();
app.use(express.json());

app.use('/api/rql', createRQLMiddleware({
  contracts: [getProductContract],
}));

app.listen(3000);

3. Query Your API

curl -X POST http://localhost:3000/api/rql \
  -H "Content-Type: application/json" \
  -d '{
    "product": {
      "contract": "getProduct",
      "params": { "productId": "prod_123" },
      "select": { "id": true, "name": true, "price": true }
    }
  }'

Response:

{
  "data": {
    "product": { "id": "prod_123", "name": "Laptop", "price": 99900 }
  },
  "errors": []
}

Relations with Batching

Define relations between contracts with automatic batching:

const getProductContract = defineContract({
  // ...
  selectable: {
    id: { type: 'string', description: 'ID' },
    manufacturerId: { type: 'string', description: 'Manufacturer ID' },
    manufacturer: {
      type: 'Manufacturer',
      description: 'Product manufacturer',
      relation: {
        contractName: 'getManufacturerById',
        params: { manufacturerId: '{{ parent.manufacturerId }}' },
        // Enable batching - 50 products = 1 batch call, not 50 calls
        batch: { param: 'manufacturerId', as: 'manufacturerIds' },
      },
    },
  },
});

Cross-Query Templating

Reference data from other queries in the same request:

{
  "mainProduct": {
    "contract": "getProduct",
    "params": { "productId": "prod_123" },
    "select": { "id": true, "categoryId": true }
  },
  "relatedProducts": {
    "contract": "getProductsByCategory",
    "params": {
      "categoryId": "{{ data.mainProduct.categoryId }}",
      "excludeId": "{{ data.mainProduct.id }}"
    },
    "select": { "id": true, "name": true }
  }
}

Schema Discovery

# Get all groups and ungrouped contracts
GET /api/rql/schema

# Get all contracts in a group
GET /api/rql/schema/Products

# Get flat list of all contracts
GET /api/rql/schema/all

# Pretty print and/or raw Zod schemas
GET /api/rql/schema?pretty=1&raw=1

Why Not GraphQL?

Feature RQL GraphQL
Learning curve Minutes Hours/Days
Schema definition TypeScript + Zod SDL
Code generation Not needed Often required
Bundle size ~20KB 50KB+
N+1 prevention Built-in batching DataLoader needed
AI compatibility Native JSON Needs parsing

RQL is ideal when you want GraphQL-like flexibility without the complexity.

Packages

Package Description
@rql-kit/core Core types, engine, and server factory
@rql-kit/express Express middleware adapter

Roadmap

v0.1 (Current)

  • βœ… Core engine with validation, relations, templating
  • βœ… Express middleware adapter
  • βœ… Schema discovery endpoints
  • βœ… Cross-query {{ data.x.y }} templating
  • βœ… Budget limits (depth, fields, queries)

v0.2 (Planned)

  • Relation batching - automatic N+1 prevention via batch metadata
  • MCP adapter - expose RQL as Model Context Protocol tools
  • Caching layer - configurable response caching
  • OpenAPI export - generate OpenAPI spec from contracts

v0.3 (Future)

  • Subscriptions - real-time data updates
  • Rate limiting - per-contract rate limits
  • Metrics/tracing - OpenTelemetry integration
  • React Query integration - typed client hooks

Documentation

License

MIT Β© 2024

About

RQL is a lightweight alternative to GraphQL designed for modern applications and AI agents

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published