**NOTE:** This CLI tool is primarily designed for use within our organization. The generated code output aligns with our internal template.
npm install @povio/openapi-codegen-cliNOTE: This CLI tool is primarily designed for use within our organization. The generated code output aligns with our internal template.
NOTE: Version 1+ requires zod v4 and is not compatible with zod v3.
NOTE: Version 2+ includes supporting classes/types/components for the generated code as well as auth, therefore it has peerDependencies for @tanstack/react-query, axios, react and zod. @casl/ability and @casl/react are also required if you are generating ACL checks and/or using imports from "@povio/openapi-codegen-cli/acl"!
Use this tool to generate code (Zod schemas, TypeScript types, API definitions, and React queries) from an OpenAPI v3 specification. API definitions are generated to use a REST client wrapper that utilizes Axios. React queries are generated in alignment with our code standards, without the need for explicit types.
The tool partially leverages code from openapi-zod-client repository.
``bash`
yarn add @povio/openapi-codegen-cli
`bash`
yarn openapi-codegen generate --input http://localhost:3001/docs-json
The CLI supports TypeScript configuration files to simplify command execution and provide consistent settings with full type safety. Configuration files are automatically discovered in your project root.
Note: Command-line arguments always take precedence over configuration file values, allowing you to override specific settings when needed.
Create an openapi-codegen.config.ts file:
`typescript
import { OpenAPICodegenConfig } from "@povio/openapi-codegen-cli";
const config: OpenAPICodegenConfig = {
input: "http://localhost:4000/docs-json/",
output: "src/data",
};
export default config;
`
Then run without arguments:
`bash`
yarn openapi-codegen generate
The CLI automatically searches for the TypeScript configuration file:
- openapi-codegen.config.ts
You can also specify a custom configuration file:
`bash`
yarn openapi-codegen generate --config my-config.ts
#### Generate command (generates Zod schemas, API definitions and React queries)
`sh
--config Path to TS config file (default: 'openapi-codegen.config.ts')
--input Path/URL to OpenAPI JSON/YAML document
--output Output directory path (default: 'output')
--format Format the generated code using Oxfmt (default: true)
--verbose Display detailed log messages during execution (default: false)
--splitByTags Organize output into separate folders based on OpenAPI operation tags (default: true)
--defaultTag (Requires --splitByTags) Default tag for shared code across multiple tags (default: 'Common')
--excludeTags Comma-separated list of tags to exclude from generation
--excludePathRegex Exclude operations whose paths match the given regular expression
--excludeRedundantZodSchemas Exclude any redundant Zod schemas (default: true)
--tsNamespaces Wrap generated files in TypeScript namespaces (default: true)
--importPath Module import style for generated files (default: 'ts'; options: 'ts' | 'relative' | 'absolute')
--tsPath (Requires --importPath to be 'ts') Typescript import path (default: '@/data').optional()
--removeOperationPrefixEndingWith Remove operation name prefixes that end with the specified string (default: 'Controller_')
--extractEnums Extract enums into separate Zod schemas (default: true)
--replaceOptionalWithNullish Replace chains with .nullish() in generated Zod schemas (default: false)
--axiosRequestConfig Include Axios request config parameters in query hooks (default: false)
--infiniteQueries Generate infinite queries for paginated API endpoints (default: false)
--mutationEffects Add mutation effects options to mutation hooks (default: true)
--parseRequestParams Add Zod parsing to API endpoints (default: true)
--acl Generate ACL related files (default: true)
--checkAcl Add ACL check to queries (default: true)
--builderConfigs Generate configs for builders (default: false)
--baseUrl (Requires --restClientImportPath to NOT be set) Base URL for the generated REST client; falls back to the OpenAPI spec if not provided`
#### Check command (checks if OpenAPI spec is compliant)
`sh
--config Path to TS config file (default: 'openapi-codegen.config.ts')
--input Path/URL to OpenAPI/Swagger document as JSON/YAML
--verbose Show log messages during execution
--splitByTags Organize output into separate folders based on OpenAPI operation tags (default: true)
--defaultTag (Requires --splitByTags) Default tag for shared code across multiple tags (default: 'Common')
--excludeTags Comma-separated list of tags to exclude from generation
--excludePathRegex Exclude operations whose paths match the given regular expression
--excludeRedundantZodSchemas Exclude any redundant Zod schemas (default: true)
`
#### Test locally
`bashprerequisites
corepack install
yarn
Common Issues
$3
In order to add interceptors to the used REST client, you must create your own instance of a RestClient and pass your implemented interceptors into the constructor. Make sure to set
restClientImportPath in your openapi generation configuration too.`ts
import { RestInterceptor } from "@povio/openapi-codegen-cli";import { ACCESS_TOKEN_KEY } from "@/config/jwt.config";
export const AuthorizationHeaderInterceptor = new RestInterceptor((client) => {
return client.interceptors.request.use(async (config) => {
const accessToken = localStorage.getItem(ACCESS_TOKEN_KEY);
if (accessToken != null) {
config.headers.Authorization =
Bearer ${accessToken};
} return config;
});
});
``ts
import { RestClient } from "@povio/openapi-codegen-cli";import { AuthorizationHeaderInterceptor } from "@/clients/rest/interceptors/authorization-header.interceptor";
import { AppConfig } from "@/config/app.config";
export const AppRestClient = new RestClient({
config: {
baseURL: AppConfig.api.url,
},
interceptors: [AuthorizationHeaderInterceptor],
});
``ts
import type { OpenAPICodegenConfig } from "@povio/openapi-codegen-cli";const config: OpenAPICodegenConfig = {
restClientImportPath: "@/clients/app-rest-client",
// ...
};
export default config;
`$3
If you're using Enums in your backend DTOs with
@Expose() and @IsEnum, they may still not appear correctly in the OpenAPI schema unless you also provide both enum and enumName to @ApiProperty.`ts
enum Status {
ACTIVE = "active",
INACTIVE = "inactive",
}export class ExampleDto {
@ApiProperty({ enum: Status, enumName: "Status" })
@Expose()
@IsEnum(Status)
status: Status;
}
``ts
enum Status {
ACTIVE = "active",
INACTIVE = "inactive",
}export class ExampleDto {
@ApiProperty({ enum: Status, enumName: "Status", isArray: true })
@Expose()
@IsEnum(Status, { each: true })
@IsArray()
status: Status[];
}
`---
$3
When using nested DTOs, ensure you explicitly specify the type using
@ApiProperty({ type: NestedDto }):`ts
export class NestedDto {
@ApiProperty()
@Expose()
name: string;
}export class ParentDto {
@ApiProperty({ type: NestedDto })
@Expose()
@ValidateNested()
@Type(() => NestedDto)
@IsObject()
nested: NestedDto;
}
``ts
export class NestedDto {
@ApiProperty()
@Expose()
name: string;
}export class ParentDto {
@ApiProperty({ type: NestedDto, isArray: true })
@Expose()
@ValidateNested({ each: true })
@Type(() => NestedDto)
@IsArray()
nestedList: NestedDto[];
}
`---
$3
When using JSON or Objects types, ensure you explicitly specify additional properties types as any otherwise FE ZOD will strip out everything:
@ApiProperty({ additionalProperties: { type: 'any' } }):`ts
export class JSONDto {
@ApiProperty()
@Expose()
@IsObject()
nested: NestedDto;
}
``ts
export class JSONDto {
@ApiProperty({ additionalProperties: { type: "any" } })
@Expose()
@IsObject()
nested: NestedDto;
}
``