npm NuGet v1.0.0 MIT

GraphQL to React Client Generator

@metaengine/graphql-react

Convert GraphQL SDL to React hooks and models with optional TanStack Query (useQuery, useMutation), typed queries, mutations & subscriptions, and the native Fetch API. React 18+.

GraphQL SDLMetaEngine IRTypeScript · React
Convert GraphQL to React in the browser
Install

Pick your registry

The same generator, published to every ecosystem we support. Install however your project expects.

npmPrimary@metaengine/graphql-react
$npm install @metaengine/graphql-react
v1.0.0
NuGetMetaEngine.TypeScript.GraphQL.React
$dotnet add package MetaEngine.TypeScript.GraphQL.React
v1.0.0
Usage

Drive it from the CLI or programmatically

npm ships a zero-config CLI. NuGet ships the same generator as a C# fluent API — same options, same output.

npm · npx · CI-friendly

After install, point the CLI at your schema. It writes the generated tree to your chosen output directory.

Basic syntax
terminal
npx @metaengine/graphql-react <input> <output> [options]

Generates React hooks and models from GraphQL schemas — typed queries, mutations & subscriptions, with optional TanStack Query over native Fetch.

Quick examples
Generate from a schema file
npx @metaengine/graphql-react schema.graphql ./src/api
With TanStack Query
npx @metaengine/graphql-react schema.graphql ./src/api \
  --tanstack-query \
  --documentation
With error handling, retries and a scalar mapping
npx @metaengine/graphql-react schema.graphql ./src/api \
  --error-handling \
  --retries 3 \
  --custom-scalar DateTime=string
CLI options
Option
Description
--fragments
Emit reusable named fragments for object-type selections
--one-of-inputs
Generate idiomatic @oneOf input types (tagged-union inputs)
--custom-scalar <Scalar=target>
Map a GraphQL custom scalar to a TS type. Repeatable. Targets: string · number · boolean · Date (e.g. DateTime=string)
--base-url-env <name>
Environment variable name for base URL [default: REACT_APP_API_BASE_URL]. Use VITE_ prefix for Vite, NEXT_PUBLIC_ for Next.js.
--tanstack-query
Enable TanStack Query integration (useQuery / useMutation)
--error-handling
Smart error handling based on HTTP status semantics
--retries <max-attempts>
Enable retries with exponential backoff (status 429, 503)
--documentation
Generate JSDoc comments from SDL descriptions
--date-transformation
Convert Date-typed scalar fields (e.g. DateTime) in responses to JavaScript Date objects
--options-threshold <n>
Parameter count to use options object [default: 4]
--service-suffix <suffix>
Service naming suffix [default: Api]
--types-barrel
Emit an index.ts barrel per folder plus a root index.ts re-exporting everything
--clean
Clean output directory (remove files not in generation)
--verbose
Enable verbose logging
--help, -h
Show help message
Options reference

Every knob, documented

Every option is available on the C# fluent API as a method, and most are also exposed as CLI flags. Cross-cutting auth, headers, retries and timeouts apply across frameworks.

React Options

4
  • WithBaseUrlEnvVar(string)Environment variable name for base URL (default: "REACT_APP_API_BASE_URL"). Use VITE_ prefix for Vite, NEXT_PUBLIC_ for Next.js.
  • WithTanStackQuery()Generate TanStack Query hooks (useQuery / useMutation). Requires @tanstack/react-query.
  • WithMiddleware()Emit fetch middleware infrastructure (Middleware type + chainMiddleware + createFetchWithMiddleware)
  • WithResponseDateTransformation()Convert Date-typed scalar fields (e.g. DateTime) in responses to Date objects

Auth · Headers · Resilience

12
  • WithErrorHandling()Smart error handling based on HTTP status semantics (404 / 403 → null · 400 / 422 / 409 → error body · 401 / 5xx → throw). GraphQL operations travel over HTTP POST.
  • WithErrorHandling(errors => errors...)Per-status routing: ReturnNullFor(404, 403) · ReturnErrorFor(400, 422) · ThrowFor(401, 500)
  • WithBearerAuth()Bearer token from env var (default API_TOKEN) — adds Authorization header
  • WithBearerAuth(string)Bearer token from a specific env var name
  • WithBearerAuth(string, string)Bearer token with custom header name
  • WithBasicAuth(string, string)HTTP Basic auth from username + password env vars
  • WithCustomHeader(string, string)Static header from env var. Repeatable (e.g. X-Tenant-ID ← TENANT_ID)
  • WithTimeout(double)Request timeout in seconds for all operations
  • WithTimeout(double?, double?, double?, double?)Granular timeout: connect · read · write · pool
  • WithRetries()Retries with exponential backoff (default status 429, 503)
  • WithRetries(int)Retries with custom max attempts
  • WithRetries(int, double, double, int[])Retries with full custom settings including status codes

GraphQL Options

7
  • WithDocumentation()Generate JSDoc comments from SDL type & field descriptions
  • WithFragments()Emit reusable named fragments for object-type selections (...TypeFields spreads)
  • WithOneOfInputs()Generate idiomatic @oneOf input types (tagged-union inputs where exactly one field is set)
  • WithCustomScalar(string, Type)Map a GraphQL custom scalar to a TS type (e.g. DateTime → Date). Unmapped scalars default to string
  • WithTypeFilter(Func)Filter extracted GraphQL types before registration — only types returning true are generated
  • WithMethodNames(Func)Custom method naming rule
  • WithOptionsObjectThreshold(int)Parameter count for options object (default: 4)

TypeScript Output

1
  • WithTypesBarrel()Emit an index.ts barrel per folder plus a root index.ts re-exporting everything

Naming Transformations

3
  • Types(Func)Transform type names
  • Paths(Func)Transform output paths
  • FileNames(Func)Transform file names

File Management

5
  • CleanDestination()Clean output directory before generation
  • AlwaysOverwrite()Always overwrite existing files
  • OnlyWhenModelChanged()Update only when model changes
  • OnlyWhenNew()Write only new files, preserve existing
  • CleanDirectories(...)Clean specific subdirectories

Diagnostics

2
  • Verbose()Enable verbose logging
  • WithLogger(Action<string>)Route generation log output to a custom sink
Features

Why this package is different

Tree-shakeable
One file per tag (or per operation) means bundlers drop unused clients at build time. No runtime dispatch table.
Strict, no any
Output compiles under strict with no any. Unions, nullability and enums are modelled precisely so tsc catches drift.
Zero runtime
The default emit is types plus a thin client — no decorators, no reflection, no dependency surface beyond your HTTP lib.
Deterministic output
Same spec + same options produce byte-identical files. Safe to commit, safe to diff in review, safe to cache in CI.
Flexible naming
Case conventions are configurable per role — types, properties, operations, enums. Idiomatic in the target by default.
Semver-honest
Spec diff drives the version bump. Additive changes = minor, removed operations = major. Never a surprise in your lockfile.