- Fixed binary format checking

This commit is contained in:
Ferdi Koomen 2021-10-29 13:36:47 +02:00
parent 9c9b2fa61c
commit 35bda10d18
11 changed files with 65 additions and 89 deletions

View File

@ -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",

View File

@ -1,4 +1,4 @@
export const TYPE_MAPPINGS = new Map<string, string>([
const TYPE_MAPPINGS = new Map<string, string>([
['File', 'File'],
['file', 'File'],
['any', 'any'],
@ -25,10 +25,9 @@ export const TYPE_MAPPINGS = new Map<string, string>([
/**
* 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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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');

View File

@ -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;

View File

@ -1,4 +1,4 @@
export const TYPE_MAPPINGS = new Map<string, string>([
const TYPE_MAPPINGS = new Map<string, string>([
['File', 'File'],
['file', 'File'],
['any', 'any'],
@ -25,10 +25,9 @@ export const TYPE_MAPPINGS = new Map<string, string>([
/**
* 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);
}

View File

@ -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;

View File

@ -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');

View File

@ -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;

View File

@ -5195,7 +5195,7 @@ export class MultipartService {
* @throws ApiError
*/
public static multipartResponse(): CancelablePromise<{
file?: string;
file?: Blob;
metadata?: {
foo?: string;
bar?: string;