fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix mapped discriminator to self leading to `$type: string` instead of string literal

+344
+7
packages/openapi-ts-tests/main/test/3.0.x.test.ts
··· 226 226 }, 227 227 { 228 228 config: createConfig({ 229 + input: 'discriminator-object-self-mapped.json', 230 + output: 'discriminator-object-self-mapped', 231 + }), 232 + description: 'handles object discriminator mappings that include the schema itself', 233 + }, 234 + { 235 + config: createConfig({ 229 236 input: 'discriminator-non-string.yaml', 230 237 output: 'discriminator-non-string', 231 238 }),
+7
packages/openapi-ts-tests/main/test/3.1.x.test.ts
··· 252 252 }, 253 253 { 254 254 config: createConfig({ 255 + input: 'discriminator-object-self-mapped.json', 256 + output: 'discriminator-object-self-mapped', 257 + }), 258 + description: 'handles object discriminator mappings that include the schema itself', 259 + }, 260 + { 261 + config: createConfig({ 255 262 input: 'discriminator-non-string.yaml', 256 263 output: 'discriminator-non-string', 257 264 }),
+3
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-object-self-mapped/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type { BlogPostDto, BlogPostWithImageDto, ClientOptions, GetBlogPostsData, GetBlogPostsResponse, GetBlogPostsResponses } from './types.gen';
+32
packages/openapi-ts-tests/main/test/__snapshots__/3.0.x/discriminator-object-self-mapped/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type ClientOptions = { 4 + baseUrl: `${string}://${string}` | (string & {}); 5 + }; 6 + 7 + export type BlogPostDto = { 8 + $type: 'BlogPost'; 9 + id: number; 10 + title: string; 11 + }; 12 + 13 + export type BlogPostWithImageDto = Omit<BlogPostDto, '$type'> & { 14 + imageUrl: string; 15 + $type: 'BlogPostWithImage'; 16 + }; 17 + 18 + export type GetBlogPostsData = { 19 + body?: never; 20 + path?: never; 21 + query?: never; 22 + url: '/blog-posts'; 23 + }; 24 + 25 + export type GetBlogPostsResponses = { 26 + /** 27 + * List of blog posts 28 + */ 29 + 200: Array<BlogPostDto | BlogPostWithImageDto>; 30 + }; 31 + 32 + export type GetBlogPostsResponse = GetBlogPostsResponses[keyof GetBlogPostsResponses];
+3
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-object-self-mapped/index.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type { BlogPostDto, BlogPostWithImageDto, ClientOptions, GetBlogPostsData, GetBlogPostsResponse, GetBlogPostsResponses } from './types.gen';
+32
packages/openapi-ts-tests/main/test/__snapshots__/3.1.x/discriminator-object-self-mapped/types.gen.ts
··· 1 + // This file is auto-generated by @hey-api/openapi-ts 2 + 3 + export type ClientOptions = { 4 + baseUrl: `${string}://${string}` | (string & {}); 5 + }; 6 + 7 + export type BlogPostDto = { 8 + $type: 'BlogPost'; 9 + id: number; 10 + title: string; 11 + }; 12 + 13 + export type BlogPostWithImageDto = Omit<BlogPostDto, '$type'> & { 14 + imageUrl: string; 15 + $type: 'BlogPostWithImage'; 16 + }; 17 + 18 + export type GetBlogPostsData = { 19 + body?: never; 20 + path?: never; 21 + query?: never; 22 + url: '/blog-posts'; 23 + }; 24 + 25 + export type GetBlogPostsResponses = { 26 + /** 27 + * List of blog posts 28 + */ 29 + 200: Array<BlogPostDto | BlogPostWithImageDto>; 30 + }; 31 + 32 + export type GetBlogPostsResponse = GetBlogPostsResponses[keyof GetBlogPostsResponses];
+57
packages/shared/src/openApi/3.0.x/parser/schema.ts
··· 150 150 return values; 151 151 }; 152 152 153 + const getMappedDiscriminatorProperty = ({ 154 + context, 155 + discriminator, 156 + schema, 157 + schemaRef, 158 + }: { 159 + context: Context; 160 + discriminator: NonNullable<SchemaObject['discriminator']>; 161 + schema: SchemaObject; 162 + schemaRef: string; 163 + }): IR.SchemaObject | undefined => { 164 + const values = getAllDiscriminatorValues({ 165 + discriminator, 166 + schemaRef, 167 + }); 168 + 169 + if (!values.length) { 170 + return; 171 + } 172 + 173 + const propertyType = findDiscriminatorPropertyType({ 174 + context, 175 + propertyName: discriminator.propertyName, 176 + schemas: [schema], 177 + }); 178 + 179 + const valueSchemas: ReadonlyArray<IR.SchemaObject> = values.map((value) => 180 + convertDiscriminatorValue(value, propertyType), 181 + ); 182 + 183 + if (valueSchemas.length === 1) { 184 + return valueSchemas[0]; 185 + } 186 + 187 + return { 188 + items: valueSchemas, 189 + logicalOperator: 'or', 190 + }; 191 + }; 192 + 153 193 const parseSchemaJsDoc = ({ 154 194 irSchema, 155 195 schema, ··· 375 415 376 416 if (schema.required) { 377 417 irSchema.required = schema.required; 418 + } 419 + 420 + if (schema.discriminator && state.$ref) { 421 + const discriminatorProperty = getMappedDiscriminatorProperty({ 422 + context, 423 + discriminator: schema.discriminator, 424 + schema, 425 + schemaRef: state.$ref, 426 + }); 427 + 428 + if (discriminatorProperty) { 429 + if (!irSchema.properties) { 430 + irSchema.properties = {}; 431 + } 432 + 433 + irSchema.properties[schema.discriminator.propertyName] = discriminatorProperty; 434 + } 378 435 } 379 436 380 437 return irSchema;
+57
packages/shared/src/openApi/3.1.x/parser/schema.ts
··· 163 163 return values; 164 164 }; 165 165 166 + const getMappedDiscriminatorProperty = ({ 167 + context, 168 + discriminator, 169 + schema, 170 + schemaRef, 171 + }: { 172 + context: Context; 173 + discriminator: NonNullable<SchemaObject['discriminator']>; 174 + schema: SchemaObject; 175 + schemaRef: string; 176 + }): IR.SchemaObject | undefined => { 177 + const values = getAllDiscriminatorValues({ 178 + discriminator, 179 + schemaRef, 180 + }); 181 + 182 + if (!values.length) { 183 + return; 184 + } 185 + 186 + const propertyType = findDiscriminatorPropertyType({ 187 + context, 188 + propertyName: discriminator.propertyName, 189 + schemas: [schema], 190 + }); 191 + 192 + const valueSchemas: ReadonlyArray<IR.SchemaObject> = values.map((value) => 193 + convertDiscriminatorValue(value, propertyType), 194 + ); 195 + 196 + if (valueSchemas.length === 1) { 197 + return valueSchemas[0]; 198 + } 199 + 200 + return { 201 + items: valueSchemas, 202 + logicalOperator: 'or', 203 + }; 204 + }; 205 + 166 206 const parseSchemaJsDoc = ({ 167 207 irSchema, 168 208 schema, ··· 470 510 471 511 if (schema.required) { 472 512 irSchema.required = schema.required; 513 + } 514 + 515 + if (schema.discriminator && state.$ref) { 516 + const discriminatorProperty = getMappedDiscriminatorProperty({ 517 + context, 518 + discriminator: schema.discriminator, 519 + schema, 520 + schemaRef: state.$ref, 521 + }); 522 + 523 + if (discriminatorProperty) { 524 + if (!irSchema.properties) { 525 + irSchema.properties = {}; 526 + } 527 + 528 + irSchema.properties[schema.discriminator.propertyName] = discriminatorProperty; 529 + } 473 530 } 474 531 475 532 return irSchema;
+73
specs/3.0.x/discriminator-object-self-mapped.json
··· 1 + { 2 + "openapi": "3.0.3", 3 + "info": { 4 + "title": "Discriminator object schema with self mapping", 5 + "version": "1.0.0", 6 + "description": "Ensures a concrete schema with a discriminator mapping to itself gets a literal discriminator value instead of falling back to string." 7 + }, 8 + "paths": { 9 + "/blog-posts": { 10 + "get": { 11 + "summary": "Get blog posts", 12 + "responses": { 13 + "200": { 14 + "description": "List of blog posts", 15 + "content": { 16 + "application/json": { 17 + "schema": { 18 + "type": "array", 19 + "items": { 20 + "oneOf": [ 21 + { "$ref": "#/components/schemas/BlogPostDto" }, 22 + { "$ref": "#/components/schemas/BlogPostWithImageDto" } 23 + ] 24 + } 25 + } 26 + } 27 + } 28 + } 29 + } 30 + } 31 + } 32 + }, 33 + "components": { 34 + "schemas": { 35 + "BlogPostDto": { 36 + "type": "object", 37 + "required": ["$type", "id", "title"], 38 + "properties": { 39 + "$type": { 40 + "type": "string" 41 + }, 42 + "id": { 43 + "type": "integer" 44 + }, 45 + "title": { 46 + "type": "string" 47 + } 48 + }, 49 + "discriminator": { 50 + "propertyName": "$type", 51 + "mapping": { 52 + "BlogPost": "#/components/schemas/BlogPostDto", 53 + "BlogPostWithImage": "#/components/schemas/BlogPostWithImageDto" 54 + } 55 + } 56 + }, 57 + "BlogPostWithImageDto": { 58 + "allOf": [ 59 + { "$ref": "#/components/schemas/BlogPostDto" }, 60 + { 61 + "type": "object", 62 + "required": ["imageUrl"], 63 + "properties": { 64 + "imageUrl": { 65 + "type": "string" 66 + } 67 + } 68 + } 69 + ] 70 + } 71 + } 72 + } 73 + }
+73
specs/3.1.x/discriminator-object-self-mapped.json
··· 1 + { 2 + "openapi": "3.1.0", 3 + "info": { 4 + "title": "Discriminator object schema with self mapping", 5 + "version": "1.0.0", 6 + "description": "Ensures a concrete schema with a discriminator mapping to itself gets a literal discriminator value instead of falling back to string." 7 + }, 8 + "paths": { 9 + "/blog-posts": { 10 + "get": { 11 + "summary": "Get blog posts", 12 + "responses": { 13 + "200": { 14 + "description": "List of blog posts", 15 + "content": { 16 + "application/json": { 17 + "schema": { 18 + "type": "array", 19 + "items": { 20 + "oneOf": [ 21 + { "$ref": "#/components/schemas/BlogPostDto" }, 22 + { "$ref": "#/components/schemas/BlogPostWithImageDto" } 23 + ] 24 + } 25 + } 26 + } 27 + } 28 + } 29 + } 30 + } 31 + } 32 + }, 33 + "components": { 34 + "schemas": { 35 + "BlogPostDto": { 36 + "type": "object", 37 + "required": ["$type", "id", "title"], 38 + "properties": { 39 + "$type": { 40 + "type": "string" 41 + }, 42 + "id": { 43 + "type": "integer" 44 + }, 45 + "title": { 46 + "type": "string" 47 + } 48 + }, 49 + "discriminator": { 50 + "propertyName": "$type", 51 + "mapping": { 52 + "BlogPost": "#/components/schemas/BlogPostDto", 53 + "BlogPostWithImage": "#/components/schemas/BlogPostWithImageDto" 54 + } 55 + } 56 + }, 57 + "BlogPostWithImageDto": { 58 + "allOf": [ 59 + { "$ref": "#/components/schemas/BlogPostDto" }, 60 + { 61 + "type": "object", 62 + "required": ["imageUrl"], 63 + "properties": { 64 + "imageUrl": { 65 + "type": "string" 66 + } 67 + } 68 + } 69 + ] 70 + } 71 + } 72 + } 73 + }