From 3340ca4bd873f9123fb7d52ed341811ac69e5120 Mon Sep 17 00:00:00 2001 From: Sergey Volkov Date: Tue, 18 Jul 2023 15:59:34 +0300 Subject: [PATCH] feat: --extract-discriminators option --- CHANGELOG.md | 2 ++ README.md | 4 +++ index.d.ts | 3 +++ index.js | 6 +++++ src/configuration.js | 2 ++ .../base-schema-parsers/discriminator.js | 27 +++++++++++++++++++ src/schema-parser/schema-utils.js | 23 ++++++++++------ 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4032ecd3..6a952097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # next release +feat: add `--extract-discriminators` option (nodejs: `extractDiscriminators`) + ## 13.0.0 BREAKING_CHANGE: disable support NodeJS 14.x diff --git a/README.md b/README.md index 12994d4f..9489f35d 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Options: --another-array-type generate array types as Array (by default Type[]) (default: false) --sort-types sort fields and types (default: false) --extract-enums extract all enums from inline interface\type content to typescript enum construction (default: false) + --extract-discriminators extract all discriminator types to their own types/interfaces (default: false) -h, --help display help for command Commands: @@ -131,6 +132,7 @@ generateApi({ extractRequestParams: false, extractRequestBody: false, extractEnums: false, + extractDiscriminators: false, unwrapResponseData: false, prettier: { // By default prettier config is load from your project printWidth: 120, @@ -149,6 +151,8 @@ generateApi({ enumKeyPrefix: '', enumKeySuffix: '', addReadonly: false, + sortRoutes: false, + sortTypes: false, extractingOptions: { requestBodySuffix: ["Payload", "Body", "Input"], requestParamsSuffix: ["Params"], diff --git a/index.d.ts b/index.d.ts index 9f063a38..eb5391bf 100644 --- a/index.d.ts +++ b/index.d.ts @@ -503,6 +503,7 @@ type ExtractingOptions = { responseErrorSuffix: string[]; requestParamsSuffix: string[]; enumSuffix: string[]; + discriminatorTypeSuffix: string[] discriminatorMappingSuffix: string[]; discriminatorAbstractPrefix: string[]; requestBodyNameResolver: (name: string, reservedNames: string) => string | undefined; @@ -510,6 +511,7 @@ type ExtractingOptions = { responseErrorNameResolver: (name: string, reservedNames: string) => string | undefined; requestParamsNameResolver: (name: string, reservedNames: string) => string | undefined; enumNameResolver: (name: string, reservedNames: string) => string | undefined; + discriminatorTypeNameResolver: (name: string, reservedNames: string) => string | undefined; discriminatorMappingNameResolver: (name: string, reservedNames: string) => string | undefined; discriminatorAbstractResolver: (name: string, reservedNames: string) => string | undefined; }; @@ -574,6 +576,7 @@ export interface GenerateApiConfiguration { extractResponseBody: boolean; extractResponseError: boolean; extractEnums: boolean; + extractDiscriminators: boolean; fixInvalidTypeNamePrefix: string; fixInvalidEnumKeyPrefix: string; defaultResponseType: string; diff --git a/index.js b/index.js index 5f382e89..7530a77b 100644 --- a/index.js +++ b/index.js @@ -233,6 +233,12 @@ const program = cli({ 'extract all enums from inline interface\\type content to typescript enum construction', default: codeGenBaseConfig.extractEnums, }, + { + flags: '--extract-discriminators', + description: + 'extract all discriminator types to their own types/interfaces', + default: codeGenBaseConfig.extractDiscriminators, + }, { flags: '--sort-routes', description: 'sort routes in alphabetical order', diff --git a/src/configuration.js b/src/configuration.js index 44bf5735..dbbd4a3d 100644 --- a/src/configuration.js +++ b/src/configuration.js @@ -75,6 +75,7 @@ class CodeGenConfig { extractResponseBody = false; extractResponseError = false; extractEnums = false; + extractDiscriminators = false; fileNames = { dataContracts: 'data-contracts', routeTypes: 'route-types', @@ -186,6 +187,7 @@ class CodeGenConfig { 'BadResponse', ], enumSuffix: ['Enum'], + discriminatorTypeSuffix: [], discriminatorMappingSuffix: ['Mapping', 'Mapper', 'MapType'], discriminatorAbstractPrefix: [ 'Base', diff --git a/src/schema-parser/base-schema-parsers/discriminator.js b/src/schema-parser/base-schema-parsers/discriminator.js index d6c247d9..f0ee7fa1 100644 --- a/src/schema-parser/base-schema-parsers/discriminator.js +++ b/src/schema-parser/base-schema-parsers/discriminator.js @@ -5,6 +5,15 @@ const { MonoSchemaParser } = require('../mono-schema-parser'); class DiscriminatorSchemaParser extends MonoSchemaParser { parse() { const { discriminator, ...noDiscriminatorSchema } = this.schema; + const pathTypeName = this.buildTypeNameFromPath(); + + if ( + this.config.extractDiscriminators && + pathTypeName != null && + !this.typeName + ) { + return this.extractType(pathTypeName); + } if (!discriminator.mapping) { return this.schemaParserFabric @@ -294,6 +303,24 @@ class DiscriminatorSchemaParser extends MonoSchemaParser { ), }; }; + + extractType = (pathTypeName) => { + const generatedTypeName = this.schemaUtils.resolveTypeName(pathTypeName, { + suffixes: this.config.extractingOptions.discriminatorTypeSuffix, + resolver: this.config.extractingOptions.discriminatorTypeNameResolver, + }); + const customComponent = this.schemaComponentsMap.createComponent( + this.schemaComponentsMap.createRef([ + 'components', + 'schemas', + generatedTypeName, + ]), + { + ...this.schema, + }, + ); + return this.schemaParserFabric.parseSchema(customComponent); + }; } module.exports = { diff --git a/src/schema-parser/schema-utils.js b/src/schema-parser/schema-utils.js index c5c02643..a2c906a1 100644 --- a/src/schema-parser/schema-utils.js +++ b/src/schema-parser/schema-utils.js @@ -189,15 +189,22 @@ class SchemaUtils { return resolver(pascalCase(typeName), reserved); }); } else { + const variants = + _.size(prefixes) || _.size(prefixes) + ? [ + ..._.map(prefixes, (prefix) => + pascalCase(`${prefix} ${typeName}`), + ), + ..._.map(suffixes, (suffix) => + pascalCase(`${typeName} ${suffix}`), + ), + ] + : [typeName]; + return this.config.componentTypeNameResolver.resolve( - [ - ...(prefixes || []).map((prefix) => - pascalCase(`${prefix} ${typeName}`), - ), - ...(suffixes || []).map((suffix) => - pascalCase(`${typeName} ${suffix}`), - ), - ], + variants, + null, + null, shouldReserve, ); }