@metaengine/graphql-fetch
GraphQL SDL → framework-agnostic TypeScript services and models with typed queries, mutations & subscriptions over native Fetch. Zero dependencies, tree-shakeable, runs on Node, browsers, Vite, SvelteKit, and Next.js.
Pick your registry
The same generator, published to every ecosystem we support. Install however your project expects.
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.
After install, point the CLI at your schema. It writes the generated tree to your chosen output directory.
npx @metaengine/graphql-fetch <input> <output> [options]Generates framework-agnostic TypeScript services and models from GraphQL schemas over native Fetch — typed queries, mutations & subscriptions.
npx @metaengine/graphql-fetch schema.graphql ./src/apinpx @metaengine/graphql-fetch schema.graphql ./src/api \
--import-meta-env \
--base-url-env VITE_API_URL \
--result-pattern \
--middleware \
--documentationnpx @metaengine/graphql-fetch schema.graphql ./src/api \
--bearer-auth API_TOKEN \
--custom-header X-Tenant-ID=TENANT_ID \
--timeout 30 \
--retries 3 \
--error-handlingEvery 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.
Fetch Options
5WithBaseUrlEnvVar(string)Environment variable name for base URL (default: "API_BASE_URL"). Enables getDefaultClient() lazy singleton.WithImportMetaEnv()Use import.meta.env instead of process.env (Vite, SvelteKit, Next.js 15+)WithResultPattern()Return ApiResult<T> for structured error handling without exceptionsWithMiddleware()Emit onRequest / onResponse / onError hooks in the generated clientWithResponseDateTransformation()Convert Date-typed scalar fields (e.g. DateTime) in responses to Date objects
Auth · Headers · Resilience
12WithErrorHandling()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 headerWithBearerAuth(string)Bearer token from a specific env var nameWithBearerAuth(string, string)Bearer token with custom header nameWithBasicAuth(string, string)HTTP Basic auth from username + password env varsWithCustomHeader(string, string)Static header from env var. Repeatable (e.g. X-Tenant-ID ← TENANT_ID)WithTimeout(double)Request timeout in seconds for all operationsWithTimeout(double?, double?, double?, double?)Granular timeout: connect · read · write · poolWithRetries()Retries with exponential backoff (default status 429, 503)WithRetries(int)Retries with custom max attemptsWithRetries(int, double, double, int[])Retries with full custom settings including status codes
GraphQL Options
8WithDocumentation()Generate JSDoc comments from SDL type & field descriptionsWithFragments()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 stringWithSubscriptionUrl(string)Override the WebSocket subscription path appended to baseUrl (default: "/graphql")WithTypeFilter(Func)Filter extracted GraphQL types before registration — only types returning true are generatedWithMethodNames(Func)Custom method naming ruleWithOptionsObjectThreshold(int)Parameter count for options object (default: 4)
TypeScript Output
1WithTypesBarrel()Emit an index.ts barrel per folder plus a root index.ts re-exporting everything
Naming Transformations
3Types(Func)Transform type namesPaths(Func)Transform output pathsFileNames(Func)Transform file names
File Management
5CleanDestination()Clean output directory before generationAlwaysOverwrite()Always overwrite existing filesOnlyWhenModelChanged()Update only when model changesOnlyWhenNew()Write only new files, preserve existingCleanDirectories(...)Clean specific subdirectories
Diagnostics
1EnableVerboseLogging()Enable detailed logging