Skip to content

Library Overview

react-openapi is a compiler that runs in the browser: it reads an OpenAPI document, validates it, transforms it into an internal resource model, and renders UI from that model. It never edits your spec, and it never falls back silently when a required extension is missing.


🏗️ Architecture

OpenAPI document (runtime fetch)
       |
  spec-loader        -> parsed spec object
       |
  spec-validator     -> errors / warnings / info messages
       |
  transformers       -> ResourceConfig[] + FieldConfig[] + relationships
       |
  AppProvider        -> AppContext (resources, schemas, auth, api client)
       |
  Admin / renderers -> routes, tables, forms, streams
Layer Module Responsibility
Load spec-loader.ts fetch JSON/YAML, resolve $ref
Validate spec-validator.ts error / warning / info rules
Transform transformers/* schema → ResourceConfig, properties → FieldConfig
State context/AppProvider.tsx, AppContext shared resources, schemas, auth, axios client
HTTP hooks/useApi.ts initApi, getApi with bearer injection
Present components/* Admin, ResourceList/Detail/Form, renderers

📦 Quick start

import { AppProvider, Admin } from "react-openapi";
import type { SpecConfiguration } from "react-openapi";

const specConfiguration: SpecConfiguration = {
  specUrl: "/api/openapi.yaml",
  baseApiUrl: "https://api.example.com/v1",
  title: "Vet Clinic Admin",
  getToken: () => localStorage.getItem("token"),
};

export default function App() {
  return (
    <AppProvider specConfiguration={specConfiguration}>
      <Admin basePath="/admin" />
    </AppProvider>
  );
}

Admin renders SideMenu plus nested routes per resource: /<basePath>/<resource> (list), /<resource>/new, /<resource>/:id (detail), /<resource>/:id/edit. Streaming (x-sse) resources render only the list.


🔄 How one resource reaches the screen

  1. The spec is fetched at mount; specValidator runs over it.
  2. Every schema carrying x-resource becomes a ResourceConfig (name, schemaName, displayName, path, streaming, pagination).
  3. Each property becomes a FieldConfig — x-order, x-label, x-hidden, x-filterable, x-sortable, x-edit-as, x-ui-type.
  4. useResource(name) adds CRUD helpers (list, get, create, update, remove, stream?) for one resource.
  5. ListCellRenderer / DetailFieldRenderer / FormFieldRenderer dispatch to the concrete control for that FieldConfig.

⚠️ Design decisions

  • Spec loaded at runtime, not compiled into the bundle.
  • Schema-to-path mapping is explicit — x-resource must equal the path segment. No pluralisation guessing.
  • No fallbacks for required extensions — missing x-primary-key, x-display-format, x-list-columns, x-label or x-order fails at transform time rather than defaulting silently.
  • Strict response parsing — paginated lists are { total?, items[] }, non-paginated lists are a plain array. No fallback chains.
  • FK options use ?limit=0 on paginated targets: a server convention meaning "return all", not documented in the spec.