diff --git a/docs/rtk-query/usage/code-generation.mdx b/docs/rtk-query/usage/code-generation.mdx index f307339267..15d6b0e9ec 100644 --- a/docs/rtk-query/usage/code-generation.mdx +++ b/docs/rtk-query/usage/code-generation.mdx @@ -316,7 +316,7 @@ const config: ConfigFile = { #### Custom HTTP resolver options -If you need to customize the HTTP request issued to your server, you user the `httpResolverOptions` option. This object is passed directly to the `SwaggerParser` instance that fetches the OpenAPI schema. +If you need to customize the HTTP request issued to your server, you can use the `httpResolverOptions` option. This object is passed directly to the `SwaggerParser` instance that fetches the OpenAPI schema. For example, you can pass custom headers or set a custom request timeout. @@ -334,3 +334,36 @@ const config: ConfigFile = { }, } ``` + +#### Additional Schemas + +By default, the only schemas that are exported are those that are referenced in endpoint definitions. Take the following NestJS example: + +```ts no-transpile title="user.controller.ts" +class User { + id: string; + name: string; +} + +class LogoutMessage { + reason: string; +} + +@ApiExtraModels(LogoutMessage) +@Controller('user') +class UserController { + getUsers(): User[] { + return this.getUsers(); + } +} +``` + +In this case, only the `User` schema would be exported even though we've added `LogoutMessage` as an extra model that will appear in the OpenAPI spec. Setting `exportAllSchemas: true` will export all available schemas, whether they're referenced in endpoint definitions or not. + +```ts no-transpile title="openapi-config.ts" +const config: ConfigFile = { + schemaFile: 'https://petstore3.swagger.io/api/v3/openapi.json', + apiFile: './src/store/emptyApi.ts', + outputFile: './src/store/petApi.ts', + exportAllSchemas: true, +} diff --git a/packages/rtk-query-codegen-openapi/src/generate.ts b/packages/rtk-query-codegen-openapi/src/generate.ts index 6e8a4d3717..f769808912 100644 --- a/packages/rtk-query-codegen-openapi/src/generate.ts +++ b/packages/rtk-query-codegen-openapi/src/generate.ts @@ -170,6 +170,7 @@ export async function generateApi( useUnknown = false, esmExtensions = false, outputRegexConstants = false, + exportAllSchemas = false, }: GenerationOptions ) { const v3Doc = (v3DocCache[spec] ??= await getV3Doc(spec, httpResolverOptions)); @@ -269,6 +270,9 @@ export async function generateApi( return regexConstants.length > 0 ? [alias, ...regexConstants] : [alias]; }) : apiGen.aliases), + ...(exportAllSchemas && v3Doc.components?.schemas + ? generateAllSchemaTypes(v3Doc.components.schemas, apiGen) + : []), ...apiGen.enumAliases, ...(hooks ? [ @@ -591,6 +595,31 @@ export async function generateApi( ); } + function generateAllSchemaTypes( + schemas: Record, + apiGen: ApiGenerator + ): (ts.InterfaceDeclaration | ts.TypeAliasDeclaration)[] { + const types: (ts.InterfaceDeclaration | ts.TypeAliasDeclaration)[] = []; + + for (const [schemaName, schema] of Object.entries(schemas)) { + if (apiGen.aliases.some((alias) => alias.name.escapedText === schemaName)) { + continue; + } + + const typeNode = apiGen.getTypeFromSchema(schema, schemaName); + const typeAlias = factory.createTypeAliasDeclaration( + [factory.createModifier(ts.SyntaxKind.ExportKeyword)], + schemaName, + undefined, + typeNode + ); + + types.push(typeAlias); + } + + return types; + } + // eslint-disable-next-line no-empty-pattern function generateQueryEndpointProps({}: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions { return {}; /* TODO needs implementation - skip for now */ diff --git a/packages/rtk-query-codegen-openapi/src/types.ts b/packages/rtk-query-codegen-openapi/src/types.ts index bdff603282..bcdd1ff324 100644 --- a/packages/rtk-query-codegen-openapi/src/types.ts +++ b/packages/rtk-query-codegen-openapi/src/types.ts @@ -131,6 +131,12 @@ export interface CommonOptions { * Will generate regex constants for pattern keywords in the schema */ outputRegexConstants?: boolean; + /** + * @default false + * If set to `true`, all schemas from the OpenAPI document will be exported, regardless of whether they are referenced by any + * endpoint definitions. + */ + exportAllSchemas?: boolean; } export type TextMatcher = string | RegExp | (string | RegExp)[];