Skip to content

VladyslavMartynov10/react-query-codegen

Repository files navigation

react-native-codegen

A TypeScript-native API codegen for React Native + React Query. Parses typed service definitions written against a typed createApi builder and generates per-endpoint hooks, query keys, prefetchers, invalidators, and barrels.

This repo is both a working Expo example and a portable template: run it directly with npm start, or copy scripts/api-codegen/ and src/shared/api/ into an existing React Native / Expo app. A demo screen under app/(tabs)/codegen.tsx shows one of the generated hooks in use.


What it generates

For every service you declare (e.g. src/shared/api/auth/Auth.service.ts), the codegen produces:

Artifact Purpose
queries/use<Name>Query.<svc>.ts One hook file per query endpoint (query, infiniteQuery, suspenseQuery, suspenseInfiniteQuery, queries, prefetch, prefetchInfiniteQuery)
mutations/use<Name>Mutation.<svc>.ts One hook file per mutation endpoint
QueryKeys.<svc>.ts Per-service query key factory
queries/index.ts, mutations/index.ts, <svc>/index.ts Barrel files
models/QueryKeys.ts Merged queryKeys object + QueryKeyType union across all services
api/index.ts Top-level barrel re-exporting every service folder

Every file is fully overwritten on each run. Never hand-edit generated files — change the service definition instead.


Quickstart

# 1. Install
bun install

# 2. Run the Expo dev server (open in Expo Go, or press `w` for web)
bun start

# 3. Edit or add a service under src/shared/api/<svc>/<Svc>.service.ts
#    (See src/shared/api/auth/Auth.service.ts for 15 example endpoints
#     covering every builder kind.)

# 4. Regenerate hooks + keys
bun run api-codegen

Navigate to the Codegen tab in the running app to see one of the generated hooks wired up end-to-end (app/(tabs)/codegen.tsx). The React Query client is provided at the root in app/_layout.tsx.

Running on a native simulator

bun ios and bun android now run expo run:ios / expo run:android — they compile a native dev build, not just start Metro. They require the native folders to exist first:

# 1. Generate native ios/ and android/ folders
bun expo prebuild          # both platforms
bun expo prebuild --clean  # wipe + regenerate

# 2. Then:
bun ios                    # builds + launches iOS
bun android                # builds + launches Android

If you only want the JS dev server (Expo Go + web), bun start is enough — no prebuild needed.

Inspect scripts/api-codegen/ir.json after a run to see exactly what the parser extracted — most surprises become obvious there.


Repo layout

react-native-codegen/
├── CLAUDE.md                     Agent guide for working in this repo
├── README.md                     This file
├── ARCHITECTURE.md               Runtime abstractions + IR design
├── package.json
├── tsconfig.json
├── app/                          Expo Router entry (file-based routing)
│   ├── _layout.tsx               Root layout — wraps tree in QueryClientProvider
│   ├── modal.tsx
│   └── (tabs)/
│       ├── _layout.tsx           Tab bar
│       ├── index.tsx             Home
│       ├── explore.tsx           Expo's default explore tab
│       └── codegen.tsx           Demo: calls a codegen-generated hook
├── components/, constants/, hooks/, assets/   Standard Expo template files
├── scripts/
│   ├── reset-project.js          Expo's reset script
│   └── api-codegen/
│       ├── INTEGRATION.md        Full integration guide (conventions, checkers, troubleshooting)
│       ├── run.ts                Entry point — orchestrates the pipeline
│       ├── parse.ts              ts-morph parser → IR
│       ├── ir-types.ts           IR + CodegenConfig types
│       ├── checkers.ts           Validation rules (run before any write)
│       ├── utils.ts              String/path/IO helpers
│       ├── codegen.config.json   Project config (paths, globs, lint command)
│       └── generators/           One file per output artifact
└── src/
    └── shared/
        └── api/
            ├── createApi.ts      Typed builder factory (~115 LOC, zero external deps)
            ├── queryClient.ts    React Query client factory
            ├── baseQuery.ts      Default HTTP client (axios)
            ├── common.api.ts     Shared model types
            ├── hooks/            Hand-written wrapper hooks over @tanstack/react-query
            ├── models/           QueryError + typed param interfaces + generated QueryKeys.ts
            └── auth/             Example service (every builder kind demonstrated)
                ├── Auth.service.ts           ← you write this
                ├── models.ts                 ← you write this
                ├── QueryKeys.auth.ts         ← generated
                ├── queries/                  ← generated
                ├── mutations/                ← generated
                └── index.ts                  ← generated

Supported builder kinds

Kind Example Output
query builder.query(fn) useXQueryService, xQueryService (fetcher), invalidateXQueryService
mutation builder.mutation(fn) useXMutationService
infiniteQuery builder.infiniteQuery(fn) useXInfiniteQueryService, xInfiniteQueryService, invalidateXInfiniteQueryService
suspenseQuery builder.suspenseQuery(fn) useXSuspenseQueryService
suspenseInfiniteQuery builder.suspenseInfiniteQuery(fn) useXSuspenseInfiniteQueryService
queries builder.queries(fn) useXQueriesService (batched)
prefetch builder.prefetch(fn) usePrefetchXService
prefetchInfiniteQuery builder.prefetchInfiniteQuery(fn) usePrefetchXInfiniteQueryService

Call-style modifiers

  • builder.X(fn) — standard
  • builder.X.hook(fn) — hook-style: fn may call React hooks, must return { queryFn }
  • builder.X.configure({ client })(fn) — per-endpoint client override

Integration into another project

See scripts/api-codegen/INTEGRATION.md for a full checklist.

TL;DR:

  1. Copy scripts/api-codegen/ into the target repo.
  2. Install deps: bun add -d ts-morph tsx, bun add @tanstack/react-query axios.
  3. Copy src/shared/api/{createApi.ts,queryClient.ts,baseQuery.ts,hooks/,models/} — the runtime contract the generated code imports from.
  4. Add "api-codegen": "tsx scripts/api-codegen/run.ts" to package.json scripts.
  5. Edit scripts/api-codegen/codegen.config.json to match your layout.
  6. Write a *.service.ts and run bun run api-codegen.

Further reading

  • HISTORY.md — why this exists: the year-long journey from hand-written hooks → bash → C++ → the current builder pattern, plus what vanilla React Query actually costs you without a codegen
  • ARCHITECTURE.md — how createApi, the IR, and the generators fit together
  • scripts/api-codegen/INTEGRATION.md — conventions, checkers, troubleshooting
  • CLAUDE.md — guide for AI agents editing this repo

License

MIT. Fork it, adapt it, ship it. The point of writing the generator in TypeScript was to make it trivial for anyone to read and modify — the license should match that intent.

About

Generate typed React Query hooks, query keys, and barrels from a single service definition.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors