Configuration file β
This project requires a configuration file.
You need to create a configuration file named api-codegen.config.{ts|js|mjs|json}. It is recommended to create api-codegen.config.ts, or you can create a configuration file with your own name and use the -c or --config option in the CLI.
use defineConfig function
This function is exported from the mobx-tanstack-query-api/cli package. It adds typings for your configuration file.
import { defineConfig } from "mobx-tanstack-query-api/cli";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig({
input: 'path-or-url-to-openapi.{yaml|json}' | object,
output: 'path-to-output-directory',
noBarrelFiles: true,
removeUnusedTypes: true,
outputType: 'one-endpoint-per-file',
})Falsy arguments to defineConfig
Each rest argument to defineConfig(...) is typed as MaybeFalsy<GenerateQueryApiParams | MaybeFalsy<GenerateQueryApiParams>[]>. Falsy values (undefined, null, '', false, 0) are dropped before flattening β they never reach the returned array. You can safely pass conditional fragments such as defineConfig(shared, flag && extraBlock, maybeArray) without wrapping them in an if.
Multiple configs β
You can pass multiple configs to defineConfig function
import { defineConfig } from "mobx-tanstack-query-api/cli";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig([
{
input: 'path-or-url-to-openapi.{yaml|json}' | object,
output: 'path-to-output-directory',
removeUnusedTypes: true,
},
{
input: 'path-or-url-to-openapi.{yaml|json}' | object,
output: 'path-to-output-directory',
},
{
input: 'path-or-url-to-openapi.{yaml|json}' | object,
output: 'path-to-output-directory',
outputType: 'one-endpoint-per-file',
}
])Conditional entries in an array
If an item uses a falsy input (see input), that object is skipped by generateApi (including when the CLI runs generateApi(defineConfig(...))). defineConfig itself still returns it in the flattened array; only codegen ignores it.
Options β
input β
Type: MaybeFalsy<string | AnyObject> β either a path or URL to an OpenAPI/Swagger file, or an OpenAPI/Swagger object inlined in the config.
Falsy values (undefined, null, '', false, 0) mean the entire configuration object is skipped by generateApi (they are not codegenβd and their output is not included in the pre-codegen disk cleanup for the batch). defineConfig does not remove these entries; filtering happens when you call generateApi.
Any other value (non-empty string or object, including {}) is treated as active input.
Sometimes it is helpful to use fetchSchemaRequestOptions to fetch an OpenAPI/Swagger file with custom request options (for example auth headers).
input: 'https://gitlab.com/api/v4/openapi.json'mixinInput β
Additional input swagger schema or spec which allows to mix two swagger files.
This might be helpful if you need to merge two OpenAPI/Swagger files.
output β
Required output directory path.
fetchSchemaRequestOptions β
Optional fetch options to fetch OpenAPI/Swagger file.
Using this option you can add auth headers, etc.
Example:
fetchSchemaRequestOptions: {
headers: {
'PRIVATE-TOKEN': `GitlabToken`,
'Authorization': `Basic ${Buffer.from('js2me:qwerty').toString('base64')}`,
}
}httpClient β
This is an important property configuration for all your generated endpoints.
Default value: 'builtin' which means use built-in http client.
You can override it to use your own http client.
Sometimes this is useful if you need to customize fetch api behavior or add your own initialization for HttpClient.
Example:
Create your own file with http client:
src/shared/api/http-client.ts
import { HttpClient } from 'mobx-tanstack-query-api';
export const myExportHttpClientName = new HttpClient({
baseUrl: 'https://mydomainforapi.com',
})src/api-codegen.config.ts
httpClient: {
exportName: 'myExportHttpClientName',
path: '@/shared/api/http-client',
}So in generated endpoint files you will see these code lines:
src/shared/api/__generated__
import { myExportHttpClientName } from "@/shared/api/http-client";
import {
Endpoint,
HttpResponse,
RequestParams,
} from "mobx-tanstack-query-api";
...
export const getMyData = new Endpoint<
HttpResponse<GetMyDataDC, GetMyDataError>,
GetMyDataParams,
any
>(
{
params: ({ query, requestParams }) => ({
path: `/api/v1/get-my-data`,
method: "GET",
query: query,
...requestParams,
}),
requiredParams: [],
operationId: "getMyData",
path: ["api", "v1", "get-my-data"],
tags: [Tag.MyData],
meta: {},
},
queryClient,
myExportHttpClientName,
);queryClient β
Same as httpClient but for queryClient.
This is an important property configuration for all your generated endpoints.
Default value: 'builtin' which means use built-in Tanstack's query client.
You can override it to use your own query client.
Sometimes this is useful if you need to add configuration for EndpointQueryClient
Example:
Create your own file with query client:
src/shared/api/query-client.ts
import { EndpointQueryClient } from 'mobx-tanstack-query-api';
export const myQueryClient = new EndpointQueryClient({
defaultOptions: {
queries: {
enableOnDemand: true,
throwOnError: true,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
staleTime: 0,
retry: false,
},
mutations: {
throwOnError: true,
},
},
})src/api-codegen.config.ts
queryClient: {
exportName: 'myQueryClient',
path: '@/shared/api/query-client',
}So in generated endpoint files you will see these code lines:
src/shared/api/__generated__
import { myQueryClient } from "@/shared/api/query-client";
import {
Endpoint,
HttpResponse,
RequestParams,
} from "mobx-tanstack-query-api";
...
export const getMyData = new Endpoint<
HttpResponse<GetMyDataDC, GetMyDataError>,
GetMyDataParams,
any
>(
{
params: ({ query, requestParams }) => ({
path: `/api/v1/get-my-data`,
method: "GET",
query: query,
...requestParams,
}),
requiredParams: [],
operationId: "getMyData",
path: ["api", "v1", "get-my-data"],
tags: [Tag.MyData],
meta: {},
},
myQueryClient,
httpClient,
);endpoint β
Same as queryClient, httpClient but for Endpoint.
import { MyEndpoint } from "@/shared/api/my-endpoint";
...
export const getMyData = new MyEndpoint<
...filterEndpoints β
This option is used to filter endpoints.
You can pass string or array of strings or regular expression which will be compared with Endpoint.operationId.
You can also pass a function to manually filter endpoints.
Example:
filterEndpoints: (endpoint) =>
endpoint.raw.operationId !== 'getMyData' &&
!endpoint.raw.route.startsWith('/my/another/data')addPathSegmentToRouteName β
This option is used to add path segment to route name.
Default: false
Examples:
// operationId: 'getById'
// path: '/api/v1/users/1'
addPathSegmentToRouteName: true, // means add 0 (api) path segmentoutput will be:
export const apiGetById = new Endpoint<...>
// [api][getById]// operationId: 'getById'
// path: '/api/v1/users/1'
addPathSegmentToRouteName: 1, // means add 1 (v1) path segmentoutput will be:
export const v1GetById = new Endpoint<...>
// [v1][getById]If you need to format route name better to use formatEndpointName
otherCodegenParams β
Other codegen params for swagger-typescript-api codegen.
See swagger-typescript-api for more info.
filterTypes β
This option is used to filter all generated types from swagger schema.
It might be helpful if you need only specific interfaces in output.
Example:
Swagger files have 3 types: DataDC, FruitsDC, MemeDC
But we need only DataDC in output
filterTypes: (type) => type.name !== 'DataDC'filterGroups β
This option is used to filter endpoint groups.
You can pass string or array of strings or regular expression which will be compared with the group name.
You can also pass a function to manually filter endpoint groups.
namespace β
Collect all exports into single namespace.
Can be helpful if you work with multiple backends.
Example: without namespace:
export * from "./endpoints";
export * from "./data-contracts";with namespace:
export * as namespaceName from "./__exports"; // exports like abovenamespaceName.login.toMutation()Example:
namespace: 'api'requestPathPrefix β
This option adds a prefix to each endpointβs request path string (the template literal passed to params, not the path array segments).
- String β inserted as-is before the OpenAPI route path (same behavior as before).
- Function β called once per endpoint at codegen time. It receives an object with
operationId,path,method, andcontractName(the generated endpoint contract variable base name, including the Zod endpoint suffix when applicable). Return the prefix string to use for that endpoint.
The callback argument type is exported as RouteBaseInfo from mobx-tanstack-query-api/cli (same shape as the routeInfo object passed to zodContracts MaybeFn options).
Example (string):
requestPathPrefix: '/__super_api_prefix'Example (function):
import type { RouteBaseInfo } from 'mobx-tanstack-query-api/cli';
requestPathPrefix: (endpoint: RouteBaseInfo) =>
endpoint.operationId.startsWith('admin') ? '/admin-api' : '/public-api',export const getMyData = new Endpoint<...>(
{
params: ({ query, requestParams }) => ({
path: `/__super_api_prefix/api/v1/get-my-data`,
method: "GET",
query: query,
...requestParams,
}),
requiredParams: [],
operationId: "getMyData",
path: ["__super_api_prefix", "api", "v1", "get-my-data"],
tags: [Tag.MyData],
meta: {},
},
myQueryClient,
httpClient,
);requestPathSuffix β
This option adds a suffix after each endpointβs request path string (the template literal in params).
- String β appended as-is after the OpenAPI route path.
- Function β same as for
requestPathPrefix: evaluated at codegen time per endpoint with aRouteBaseInfoargument (operationId,path,method,contractName).
Example (string):
requestPathSuffix: '/__super_api_fx'output:
export const getMyData = new Endpoint<...>(
{
params: ({ query, requestParams }) => ({
path: `/api/v1/get-my-data/__super_api_fx`,
method: "GET",
query: query,
...requestParams,
}),
requiredParams: [],
operationId: "getMyData",
path: ["api", "v1", "get-my-data", "__super_api_fx"],
tags: [Tag.MyData],
meta: {},
},
myQueryClient,
httpClient,
);Example (function):
import type { RouteBaseInfo } from 'mobx-tanstack-query-api/cli';
requestPathSuffix: (endpoint: RouteBaseInfo) =>
endpoint.method.toLowerCase() === 'post' ? '/async' : '',output:
export const getMyData = new Endpoint<...>(
{
params: ({ query, requestParams }) => ({
path: `/api/v1/get-my-data/async`,
method: "POST",
query: query,
...requestParams,
}),
requiredParams: [],
operationId: "getMyData",
path: ["api", "v1", "get-my-data", "async"],
tags: [Tag.MyData],
meta: {},
},
myQueryClient,
httpClient,
);removeUnusedTypes β
This option removes all data contracts which are not used in any endpoint.
Default: false
This is slow operation
Example:
removeUnusedTypes: true
// or
removeUnusedTypes: {
keepTypes: ['MySuperType']
}zodContracts β
Enables generation of Zod contracts (contract) for each endpoint and (optionally) validation of input parameters and response data via validateContract at runtime.
Requires zod to be installed.
Options:
trueβ generate contracts and enable validation for bothparamsanddata:
zodContracts: true
// β in the generated Endpoint config:
// contract: <...>,
// validateContract: true,false(or omitting the field) β do not generatecontractand do not enable validation.{ validate: boolean }β always enable or disable validation (for bothparamsanddata) with a boolean value:
zodContracts: {
validate: true,
}
// β validateContract: true,
zodContracts: {
validate: false,
}
// β validateContract: false,{ validate: string }β specify an expression that will be inserted into the code as-is (e.g., enable validation only in dev environment):
zodContracts: {
validate: "process.env.NODE_ENV === 'development'",
}
// β validateContract: process.env.NODE_ENV === 'development',{ validate: (contractName, routeInfo) => ... }β computevalidateContractat codegen time for each endpoint. The function may return a boolean, a runtime expression string, or an object with separateparams/datarules:
zodContracts: {
validate: (contractName, routeInfo) => ({
params: contractName.endsWith('Contract'),
data: routeInfo.method === 'post',
}),
}
// β validateContract: { params: true, data: true },{ validate: { params?: boolean | string; data?: boolean | string } }β control validation ofparamsanddataseparately; each value can be a boolean or a string expression:
zodContracts: {
validate: {
// always validate input parameters
params: true,
// validate data only in development
data: "process.env.NODE_ENV === 'development'",
},
}
// β validateContract: { params: true, data: process.env.NODE_ENV === 'development' },When using the object form, you can also set:
suffixβ suffix for all generated Zod contract variables. Default:"Contract":
zodContracts: {
validate: true,
suffix: "Validator",
}
// β shared file: contracts.ts
// β export const nodePageEnvelopeValidator = ...
// β export const getBinaryReportValidator = { ... }appendRuleβ one field, either a string (runtime) or a function (codegen-time):- string: expression inserted as-is β
contract: <expression> ? <contractVar> : undefined(e.g. enable contracts only in development). - function
(contractName, routeInfo) => boolean: at codegen time, includecontract: <contractVar>only when the function returnstrue; otherwisecontract: undefined. The contract variable is still generated; only its inclusion in the endpoint config is conditional.
- string: expression inserted as-is β
// Runtime condition (string)
zodContracts: {
validate: true,
appendRule: 'process.env.NODE_ENV === "development"',
}
// β contract: process.env.NODE_ENV === "development" ? getBinaryReportContract : undefined,
// Codegen-time filter (function)
zodContracts: {
validate: true,
appendRule: (name) => name === 'getBinaryReportContract',
}
// β contract: getBinaryReportContract,
zodContracts: {
validate: true,
appendRule: () => false,
}
// β contract: undefined,throwβ controlthrowContracts(throw on validation errors vs. only warn):{ throw: boolean }β setthrowContractsto that boolean.{ throw: string }β setthrowContractsto an expression (inserted as-is).{ throw: (contractName, routeInfo) => ... }β computethrowContractsat codegen time for each endpoint. The function may return a boolean, a runtime expression string, or an object with separateparams/datarules.{ throw: { params?: boolean | string; data?: boolean | string } }β setthrowContractsto an object; each value is a boolean or a string expression.
zodContracts: {
validate: true,
throw: true,
}
// β validateContract: true, throwContracts: true,
zodContracts: {
validate: { params: true, data: true },
throw: { params: true, data: "process.env.NODE_ENV === 'development'" },
}
// β validateContract: { params: true, data: true }, throwContracts: { params: true, data: process.env.NODE_ENV === 'development' },
zodContracts: {
validate: true,
throw: (contractName, routeInfo) =>
routeInfo.operationId === 'getBinaryReport' && contractName.endsWith('Contract'),
}
// β throwContracts: true,Runtime logic:
validateContract: trueβ bothparamsanddataare validated;validateContract: falseorundefinedβ validation is not performed;validateContract: { params?: boolean; data?: boolean }β only the parts where the value istrueare validated.throwContractsβ whentrue, validation errors throw; whenfalseor omitted, only warnings are logged. Object form controlsparams/dataindependently.
formatEndpointName β
This option allows to format endpoint name.
Example:
formatEndpointName: (endpointName, endpointData) => {
return `${endpointName}Endpoint`;
}
// `getMyData` -> `getMyDataEndpoint`groupBy β
This option allows to group endpoints into object.
Default: false
You can group endpoints by:
tag- endpoint tag (first tag)tag-{number}- specific endpoint tag index numberpath-segment- endpoint path segment (first path segment)path-segment-{number}- specific endpoint path segment index number- custom behavior with function
Example:
groupBy: 'tag'groupBy: endpoint =>
endpoint.raw.route.includes('users') ? 'users' : 'other'groupBy: endpoint => {
if (endpoint.raw && 'x-ogen-operation-group' in endpoint.raw) {
return endpoint.raw['x-ogen-operation-group'];
}
return endpoint.tags?.[0] ?? 'other';
}formatExportGroupName β
This option allows to format endpoints group export name.
Example:
formatExportGroupName: (groupName) => {
return `${groupName}Api`;
}outputType β
This option allows to choose output type.
Default: one-endpoint-per-file
Variants:
one-endpoint-per-file- one file per endpoint
Example with groups:
* outputdir
* groupname
* index.ts
* endpoints
* index.ts
* get-endpoint-1.ts
* get-endpoint-n.tsExample without groups:
* outputdir
* index.ts
* endpoints
* index.ts
* get-endpoint-1.ts
* get-endpoint-n.tsendpoints-per-file- all endpoints in one file Example with groups:
* outputdir
* groupname
* index.ts
* endpoints.tsExample without groups:
* outputdir
* index.ts
* endpoints.tsrequestMeta β
This option allows to add some meta information for endpoint request.
Can be helpful if you need to customize the base URL for http request.
The tmplData field may be either a string or a plain object (Record<string, unknown>-style):
- String β inserted into generated code as-is (a TypeScript expression fragment). Use this when you need non-JSON syntax (unquoted keys, enums, variables, etc.).
- Object β at codegen time the value is turned into source via
JSON.stringify, so the generated file contains a JSON-shaped object literal (e.g. double-quoted keys and string values).
You may pass either a function (route, utils) => { tmplData } (per-endpoint) or a static object { tmplData } shared by all endpoints.
The legacy name getRequestMeta still works but is deprecated: codegen prints a warning and it will be removed in a future release.
Example (string β expression pasted into output):
requestMeta: () => ({
tmplData: `{ service: 'auth' }`,
}),Example (static object β same tmplData for every endpoint):
requestMeta: {
tmplData: `{ service: 'auth' }`,
},Example (object β serialized with JSON.stringify at codegen):
requestMeta: () => ({
tmplData: { service: 'auth' },
}),export const getFruits = new Endpoint<
HttpResponse<GetFruitsDataDC, GetRolesErrorDC>,
GetFruitsParams,
any
>(
{
params: ({ query, requestParams }) => ({
path: `/fruits`,
method: "GET",
meta: { service: 'auth' },
query: query,
secure: true,
...requestParams,
}),
},
...
queryClient,
httpClient,
);endpointMeta β
This option allows to add some meta information for endpoint.
Fields:
tmplData(required) β value for the endpointβsmetafield in generated code. Same rules as inrequestMeta: string is emitted as-is; plain object is serialized withJSON.stringifyat codegen time.typeName(optional) β TypeScript type for the third generic ofEndpoint<Response, Params, Meta>. You only need this field: write any valid type text (inline object, union,Pick<β¦>, etc.).typeNameImportPathis not required to get a typedMeta. IftypeNameis omitted, codegen usesanyfor that generic.typeNameImportPath(optional) β use only when the meta type must be imported from another file. If you set it, codegen addsimport { <typeName> } from "<typeNameImportPath>"to the endpoint file, sotypeNamemust then be the exported identifier (e.g.MyEndpointMeta), not an inline{ ... }type. If you omittypeNameImportPath, no import is emitted β typical for inline types in the generic.
You may pass either a function (route, utils) => { tmplData, ... } or a static object with the same shape (shared by all endpoints).
The legacy name getEndpointMeta still works but is deprecated: codegen prints a warning and it will be removed in a future release.
Example:
endpointMeta: () => ({
typeName: `{ somedata: string }`,
tmplData: `{ somedata: '123' }`,
}),Example (static object):
endpointMeta: {
typeName: `{ somedata: string }`,
tmplData: `{ somedata: '123' }`,
},Example with tmplData as an object (codegen applies JSON.stringify):
endpointMeta: () => ({
typeName: `{ somedata: string }`,
tmplData: { somedata: '123' },
}),export const getFruits = new Endpoint<
HttpResponse<GetFruitsDataDC, GetRolesErrorDC>,
GetFruitsParams,
{ somedata: string }
>(
{
params: ({ query, requestParams }) => ({
path: `/fruits`,
method: "GET",
query: query,
secure: true,
...requestParams,
}),
operationId: "getFruits",
path: ["fruits"],
tags: [Tag.Frutis],
meta: { somedata: '123' },
},
...
queryClient,
httpClient,
);
getFruits.meta.somedata; // '123'noMetaInfo β
Allows to disable generation meta-info.ts file
noBarrelFiles β
Disables generation of all index.ts barrel files in output.
Default: false
Example:
noBarrelFiles: trueExample without groups, one-endpoint-per-file:
* outputdir
* endpoints
* get-endpoint-1.ts
* get-endpoint-n.ts
* data-contracts.ts