TUTORIAL 06 · INTERMEDIATE
Generate OpenAPI and a TypeScript SDK
Generate an OpenAPI 3.1 contract and typed TypeScript client from the same ServiceDesk requirements.
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.tsInspect 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.