From 35bda10d18ab488d1e7ff4c67e00c9837aa47ae7 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Fri, 29 Oct 2021 13:36:47 +0200 Subject: [PATCH] - Fixed binary format checking --- package.json | 2 +- src/openApi/v2/parser/getMappedType.ts | 11 ++-- src/openApi/v2/parser/getModel.ts | 2 +- .../v2/parser/getOperationParameter.ts | 6 +- src/openApi/v2/parser/getType.spec.ts | 8 --- src/openApi/v2/parser/getType.ts | 43 +++++++------- src/openApi/v3/parser/getMappedType.ts | 11 ++-- src/openApi/v3/parser/getModel.ts | 2 +- src/openApi/v3/parser/getType.spec.ts | 9 --- src/openApi/v3/parser/getType.ts | 58 +++++++++---------- test/__snapshots__/index.spec.js.snap | 2 +- 11 files changed, 65 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index 66661624..cdf9a81d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.11.7", + "version": "0.11.8", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", diff --git a/src/openApi/v2/parser/getMappedType.ts b/src/openApi/v2/parser/getMappedType.ts index 85120a07..f0ccb3ee 100644 --- a/src/openApi/v2/parser/getMappedType.ts +++ b/src/openApi/v2/parser/getMappedType.ts @@ -1,4 +1,4 @@ -export const TYPE_MAPPINGS = new Map([ +const TYPE_MAPPINGS = new Map([ ['File', 'File'], ['file', 'File'], ['any', 'any'], @@ -25,10 +25,9 @@ export const TYPE_MAPPINGS = new Map([ /** * Get mapped type for given type to any basic Typescript/Javascript type. */ -export function getMappedType(type: string): string | undefined { +export function getMappedType(type: string, format?: string): string | undefined { + if (format === 'binary') { + return 'File'; + } return TYPE_MAPPINGS.get(type); } - -export function hasMappedType(type: string): boolean { - return TYPE_MAPPINGS.has(type); -} diff --git a/src/openApi/v2/parser/getModel.ts b/src/openApi/v2/parser/getModel.ts index a81f5e76..dbf75107 100644 --- a/src/openApi/v2/parser/getModel.ts +++ b/src/openApi/v2/parser/getModel.ts @@ -153,7 +153,7 @@ export function getModel( // If the schema has a type than it can be a basic or generic type. if (definition.type) { - const definitionType = getType(definition.type); + const definitionType = getType(definition.type, definition.format); model.export = 'generic'; model.type = definitionType.type; model.base = definitionType.base; diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index c31d0835..08394069 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -84,7 +84,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame } if (parameter.type === 'array' && parameter.items) { - const items = getType(parameter.items.type); + const items = getType(parameter.items.type, parameter.items.format); operationParameter.export = 'array'; operationParameter.type = items.type; operationParameter.base = items.base; @@ -95,7 +95,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame } if (parameter.type === 'object' && parameter.items) { - const items = getType(parameter.items.type); + const items = getType(parameter.items.type, parameter.items.format); operationParameter.export = 'dictionary'; operationParameter.type = items.type; operationParameter.base = items.base; @@ -137,7 +137,7 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame // If the parameter has a type than it can be a basic or generic type. if (parameter.type) { - const definitionType = getType(parameter.type); + const definitionType = getType(parameter.type, parameter.format); operationParameter.export = 'generic'; operationParameter.type = definitionType.type; operationParameter.base = definitionType.base; diff --git a/src/openApi/v2/parser/getType.spec.ts b/src/openApi/v2/parser/getType.spec.ts index acbeb712..575d2d46 100644 --- a/src/openApi/v2/parser/getType.spec.ts +++ b/src/openApi/v2/parser/getType.spec.ts @@ -49,14 +49,6 @@ describe('getType', () => { expect(type.imports).toEqual(['Link', 'Link']); }); - it('should convert generic', () => { - const type = getType('#/definitions/Link', 'Link'); - expect(type.type).toEqual('T'); - expect(type.base).toEqual('T'); - expect(type.template).toEqual(null); - expect(type.imports).toEqual([]); - }); - it('should support dot', () => { const type = getType('#/definitions/model.000'); expect(type.type).toEqual('model_000'); diff --git a/src/openApi/v2/parser/getType.ts b/src/openApi/v2/parser/getType.ts index eca9f28a..49905623 100644 --- a/src/openApi/v2/parser/getType.ts +++ b/src/openApi/v2/parser/getType.ts @@ -1,5 +1,5 @@ import type { Type } from '../../../client/interfaces/Type'; -import { getMappedType, hasMappedType } from './getMappedType'; +import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; function encode(value: string): string { @@ -8,10 +8,10 @@ function encode(value: string): string { /** * Parse any string value into a type object. - * @param value String value like "integer" or "Link[Model]". - * @param template Optional template class from parent (needed to process generics) + * @param type String value like "integer" or "Link[Model]". + * @param format String value like "binary" or "date". */ -export function getType(value?: string, template?: string): Type { +export function getType(type: string = 'any', format?: string): Type { const result: Type = { type: 'any', base: 'any', @@ -20,10 +20,17 @@ export function getType(value?: string, template?: string): Type { isNullable: false, }; - const valueClean = decodeURIComponent(stripNamespace(value || '')); + const mapped = getMappedType(type, format); + if (mapped) { + result.type = mapped; + result.base = mapped; + return result; + } - if (/\[.*\]$/g.test(valueClean)) { - const matches = valueClean.match(/(.*?)\[(.*)\]$/); + const typeWithoutNamespace = decodeURIComponent(stripNamespace(type)); + + if (/\[.*\]$/g.test(typeWithoutNamespace)) { + const matches = typeWithoutNamespace.match(/(.*?)\[(.*)\]$/); if (matches?.length) { const match1 = getType(encode(matches[1])); const match2 = getType(encode(matches[2])); @@ -44,26 +51,16 @@ export function getType(value?: string, template?: string): Type { result.imports.push(...match1.imports); result.imports.push(...match2.imports); + return result; } - } else if (hasMappedType(valueClean)) { - const mapped = getMappedType(valueClean); - if (mapped) { - result.type = mapped; - result.base = mapped; - } - } else if (valueClean) { - const type = encode(valueClean); + } + + if (typeWithoutNamespace) { + const type = encode(typeWithoutNamespace); result.type = type; result.base = type; result.imports.push(type); - } - - // If the property that we found matched the parent template class - // Then ignore this whole property and return it as a "T" template property. - if (result.type === template) { - result.type = 'T'; // Template; - result.base = 'T'; // Template; - result.imports = []; + return result; } return result; diff --git a/src/openApi/v3/parser/getMappedType.ts b/src/openApi/v3/parser/getMappedType.ts index 85120a07..f0ccb3ee 100644 --- a/src/openApi/v3/parser/getMappedType.ts +++ b/src/openApi/v3/parser/getMappedType.ts @@ -1,4 +1,4 @@ -export const TYPE_MAPPINGS = new Map([ +const TYPE_MAPPINGS = new Map([ ['File', 'File'], ['file', 'File'], ['any', 'any'], @@ -25,10 +25,9 @@ export const TYPE_MAPPINGS = new Map([ /** * Get mapped type for given type to any basic Typescript/Javascript type. */ -export function getMappedType(type: string): string | undefined { +export function getMappedType(type: string, format?: string): string | undefined { + if (format === 'binary') { + return 'File'; + } return TYPE_MAPPINGS.get(type); } - -export function hasMappedType(type: string): boolean { - return TYPE_MAPPINGS.has(type); -} diff --git a/src/openApi/v3/parser/getModel.ts b/src/openApi/v3/parser/getModel.ts index 23e151db..b9075a24 100644 --- a/src/openApi/v3/parser/getModel.ts +++ b/src/openApi/v3/parser/getModel.ts @@ -180,7 +180,7 @@ export function getModel( // If the schema has a type than it can be a basic or generic type. if (definition.type) { - const definitionType = getType(definition.type); + const definitionType = getType(definition.type, definition.format); model.export = 'generic'; model.type = definitionType.type; model.base = definitionType.base; diff --git a/src/openApi/v3/parser/getType.spec.ts b/src/openApi/v3/parser/getType.spec.ts index 33b8d9a5..06e23f37 100644 --- a/src/openApi/v3/parser/getType.spec.ts +++ b/src/openApi/v3/parser/getType.spec.ts @@ -55,15 +55,6 @@ describe('getType', () => { expect(type.isNullable).toEqual(false); }); - it('should convert generic', () => { - const type = getType('#/components/schemas/Link', 'Link'); - expect(type.type).toEqual('T'); - expect(type.base).toEqual('T'); - expect(type.template).toEqual(null); - expect(type.imports).toEqual([]); - expect(type.isNullable).toEqual(false); - }); - it('should support dot', () => { const type = getType('#/components/schemas/model.000'); expect(type.type).toEqual('model_000'); diff --git a/src/openApi/v3/parser/getType.ts b/src/openApi/v3/parser/getType.ts index e2a87748..d62453db 100644 --- a/src/openApi/v3/parser/getType.ts +++ b/src/openApi/v3/parser/getType.ts @@ -1,5 +1,6 @@ import type { Type } from '../../../client/interfaces/Type'; -import { getMappedType, hasMappedType } from './getMappedType'; +import { isDefined } from '../../../utils/isDefined'; +import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; function encode(value: string): string { @@ -8,10 +9,10 @@ function encode(value: string): string { /** * Parse any string value into a type object. - * @param values String or String[] value like "integer", "Link[Model]" or ["string", "null"] - * @param template Optional template class from parent (needed to process generics) + * @param type String or String[] value like "integer", "Link[Model]" or ["string", "null"]. + * @param format String value like "binary" or "date". */ -export function getType(values?: string | string[], template?: string): Type { +export function getType(type: string | string[] = 'any', format?: string): Type { const result: Type = { type: 'any', base: 'any', @@ -22,22 +23,29 @@ export function getType(values?: string | string[], template?: string): Type { // Special case for JSON Schema spec (december 2020, page 17), // that allows type to be an array of primitive types... - if (Array.isArray(values)) { - const type = values + if (Array.isArray(type)) { + const joinedType = type .filter(value => value !== 'null') - .filter(value => hasMappedType(value)) - .map(value => getMappedType(value)) + .map(value => getMappedType(value, format)) + .filter(isDefined) .join(' | '); - result.type = type; - result.base = type; - result.isNullable = values.includes('null'); + result.type = joinedType; + result.base = joinedType; + result.isNullable = type.includes('null'); return result; } - const valueClean = decodeURIComponent(stripNamespace(values || '')); + const mapped = getMappedType(type, format); + if (mapped) { + result.type = mapped; + result.base = mapped; + return result; + } - if (/\[.*\]$/g.test(valueClean)) { - const matches = valueClean.match(/(.*?)\[(.*)\]$/); + const typeWithoutNamespace = decodeURIComponent(stripNamespace(type)); + + if (/\[.*\]$/g.test(typeWithoutNamespace)) { + const matches = typeWithoutNamespace.match(/(.*?)\[(.*)\]$/); if (matches?.length) { const match1 = getType(encode(matches[1])); const match2 = getType(encode(matches[2])); @@ -58,26 +66,16 @@ export function getType(values?: string | string[], template?: string): Type { result.imports.push(...match1.imports); result.imports.push(...match2.imports); + return result; } - } else if (hasMappedType(valueClean)) { - const mapped = getMappedType(valueClean); - if (mapped) { - result.type = mapped; - result.base = mapped; - } - } else if (valueClean) { - const type = encode(valueClean); + } + + if (typeWithoutNamespace) { + const type = encode(typeWithoutNamespace); result.type = type; result.base = type; result.imports.push(type); - } - - // If the property that we found matched the parent template class - // Then ignore this whole property and return it as a "T" template property. - if (result.type === template) { - result.type = 'T'; // Template; - result.base = 'T'; // Template; - result.imports = []; + return result; } return result; diff --git a/test/__snapshots__/index.spec.js.snap b/test/__snapshots__/index.spec.js.snap index b877d666..bc880639 100644 --- a/test/__snapshots__/index.spec.js.snap +++ b/test/__snapshots__/index.spec.js.snap @@ -5195,7 +5195,7 @@ export class MultipartService { * @throws ApiError */ public static multipartResponse(): CancelablePromise<{ - file?: string; + file?: Blob; metadata?: { foo?: string; bar?: string;