TUTORIAL 06 · INTERMEDIATE

Generate OpenAPI and a TypeScript SDK

Generate an OpenAPI 3.1 contract and typed TypeScript client from the same ServiceDesk requirements.

RAIQL 1.020 minProject: ServiceDesk
By the end of this tutorial
  • Generate OpenAPI 3.1
  • Generate a typed client
  • Carry JWT and tenant context through the SDK
  • Keep API contract aligned with generated routes

Request API artifacts

The important property is that the OpenAPI document and client are generated from the same compiled IR as the API routes.

app.raiql
CREATE APPLICATION "RAIQL ServiceDesk";
TYPE WEB;

USE STACK
  FRONTEND NEXTJS,
  BACKEND NEXTJS,
  DATABASE POSTGRESQL;

CREATE TENANT ENTITY Tenant;
CREATE USER ENTITY User;

CREATE ENTITY Ticket (
  id UUID PRIMARY,
  title STRING REQUIRED,
  description STRING,
  status STRING REQUIRED,
  priority STRING REQUIRED,
  ownerId UUID REQUIRED,
  tenantId UUID REQUIRED
);

CREATE CRUD Tenant;
CREATE API Tenant;
CREATE CRUD Ticket;
CREATE API Ticket;

ADD AUTHENTICATION EMAIL_PASSWORD, JWT;
ADD ROLE ADMIN, AGENT, USER;
DEFAULT ROLE USER;

RELATE Ticket.ownerId TO User.id;
RELATE Ticket.tenantId TO Tenant.id;
OWN Ticket BY ownerId;
TENANT Ticket BY tenantId;

ALLOW ADMIN CREATE Ticket, READ Ticket, UPDATE Ticket, DELETE Ticket, CREATE Tenant, READ Tenant, UPDATE Tenant, DELETE Tenant;
ALLOW AGENT READ Ticket, UPDATE Ticket;
ALLOW USER CREATE OWN Ticket, READ OWN Ticket, UPDATE OWN Ticket;

ENVIRONMENT development, staging, production;
SECRET DATABASE_URL;
SECRET RAIQL_JWT_SECRET;

GENERATE OPENAPI;
GENERATE SDK TYPESCRIPT;

BUILD;
DEPLOY DOCKER;

Generate the artifacts

terminal
raiql validate
raiql generate
ls generated/openapi.json
ls generated/sdk/typescript/client.ts

Inspect the OpenAPI contract

terminal
cd generated
node -e 'const o=require("./openapi.json"); console.log(o.openapi, Object.keys(o.paths))'

Use the generated client

The exact generated methods follow the declared API/entity surface. Tenant-aware applications can set tenant context, and secure applications attach the JWT to API calls.

TypeScript
import { RaiqlClient } from "./sdk/typescript/client";

const client = new RaiqlClient({ baseUrl: "http://localhost:3000" });
client.setToken(jwt);
client.setTenant(tenantId);

const tickets = await client.listTicket();

Contract rule

RAIQL ruleDo not maintain a second hand-written API description. The RAIQL source should remain the requirement contract that drives routes, OpenAPI and SDK generation together.