- Added tests

This commit is contained in:
Ferdi Koomen 2019-11-23 20:01:29 +01:00
parent b92a02a907
commit 00158b4af7
53 changed files with 4931 additions and 383 deletions

View File

@ -10,14 +10,20 @@
"node": true,
"jest": true
},
"plugins": [
"sort-imports-es6-autofix"
],
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"prettier/prettier": [
"error"
]
"sort-imports-es6-autofix/sort-imports-es6": [2, {
"ignoreCase": false,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
}],
"prettier/prettier": ["error"]
}
}

View File

@ -79,6 +79,7 @@
"eslint": "6.6.0",
"eslint-config-prettier": "6.7.0",
"eslint-plugin-prettier": "3.1.1",
"eslint-plugin-sort-imports-es6-autofix": "0.5.0",
"glob": "7.1.6",
"handlebars": "4.5.3",
"jest": "24.9.0",

View File

@ -1,11 +1,11 @@
import * as path from 'path';
import * as ts from 'typescript';
import { OpenApiVersion, getOpenApiVersion } from './utils/getOpenApiVersion';
import { getOpenApiSpec } from './utils/getOpenApiSpec';
import { parse as parseV2 } from './openApi/v2';
import { parse as parseV3 } from './openApi/v3';
import { readHandlebarsTemplates } from './utils/readHandlebarsTemplates';
import { getOpenApiSpec } from './utils/getOpenApiSpec';
import { writeClient } from './utils/writeClient';
import * as ts from 'typescript';
import { getOpenApiVersion, OpenApiVersion } from './utils/getOpenApiVersion';
export enum Language {
TYPESCRIPT = 'typescript',

View File

@ -1,9 +1,9 @@
import { OpenApi } from './interfaces/OpenApi';
import { Client } from '../../client/interfaces/Client';
import { getServer } from './parser/getServer';
import { getServices } from './parser/getServices';
import { OpenApi } from './interfaces/OpenApi';
import { getModels } from './parser/getModels';
import { getServer } from './parser/getServer';
import { getServiceVersion } from './parser/getServiceVersion';
import { getServices } from './parser/getServices';
/**
* Parse the OpenAPI specification to a Client model that contains

View File

@ -1,6 +1,6 @@
import { OpenApiItems } from './OpenApiItems';
import { OpenApiSchema } from './OpenApiSchema';
import { OpenApiReference } from './OpenApiReference';
import { OpenApiSchema } from './OpenApiSchema';
/**
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject

View File

@ -1,8 +1,8 @@
import { Dictionary } from '../../../utils/types';
import { OpenApiExample } from './OpenApiExample';
import { OpenApiHeader } from './OpenApiHeader';
import { OpenApiSchema } from './OpenApiSchema';
import { OpenApiReference } from './OpenApiReference';
import { OpenApiSchema } from './OpenApiSchema';
/**
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#responseObject

View File

@ -1,7 +1,7 @@
import { Dictionary } from '../../../utils/types';
import { OpenApiExternalDocs } from './OpenApiExternalDocs';
import { OpenApiXml } from './OpenApiXml';
import { OpenApiReference } from './OpenApiReference';
import { OpenApiXml } from './OpenApiXml';
/**
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject

View File

@ -1,13 +1,13 @@
import { Model } from '../../../client/interfaces/Model';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiSchema } from '../interfaces/OpenApiSchema';
import { getComment } from './getComment';
import { getType } from './getType';
import { Model } from '../../../client/interfaces/Model';
import { PrimaryType } from './constants';
import { getEnumType } from './getEnumType';
import { getComment } from './getComment';
import { getEnum } from './getEnum';
import { getEnumFromDescription } from './getEnumFromDescription';
import { getEnumType } from './getEnumType';
import { getModelProperties } from './getModelProperties';
import { getType } from './getType';
export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty: boolean = false, name: string = ''): Model {
const model: Model = {
@ -20,8 +20,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty
description: getComment(definition.description),
isProperty: isProperty,
isReadOnly: definition.readOnly || false,
isRequired: false,
isNullable: false,
isRequired: false,
imports: [],
extends: [],
enum: [],

View File

@ -1,9 +1,9 @@
import { Model } from '../../../client/interfaces/Model';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiSchema } from '../interfaces/OpenApiSchema';
import { getComment } from './getComment';
import { getType } from './getType';
import { Model } from '../../../client/interfaces/Model';
import { getModel } from './getModel';
import { getType } from './getType';
export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema): Model[] {
const models: Model[] = [];

View File

@ -1,15 +1,14 @@
import { Service } from '../../../client/interfaces/Service';
import { getServiceClassName } from './getServiceClassName';
import { OpenApiOperation } from '../interfaces/OpenApiOperation';
import { getOperationName } from './getOperationName';
import { getOperationPath } from './getOperationPath';
import { OpenApi } from '../interfaces/OpenApi';
import { getComment } from './getComment';
import { OpenApiOperation } from '../interfaces/OpenApiOperation';
import { Operation } from '../../../client/interfaces/Operation';
import { getComment } from './getComment';
import { getOperationErrors } from './getOperationErrors';
import { getOperationName } from './getOperationName';
import { getOperationParameters } from './getOperationParameters';
import { getOperationPath } from './getOperationPath';
import { getOperationResponses } from './getOperationResponses';
import { getOperationResults } from './getOperationResults';
import { getOperationErrors } from './getOperationErrors';
import { getServiceClassName } from './getServiceClassName';
export function getOperation(openApi: OpenApi, url: string, method: string, op: OpenApiOperation): Operation {
const serviceName = (op.tags && op.tags[0]) || 'Service';

View File

@ -1,5 +1,5 @@
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { OperationError } from '../../../client/interfaces/OperationError';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
export function getOperationErrors(operationResponses: OperationResponse[]): OperationError[] {
return operationResponses

View File

@ -1,15 +1,15 @@
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OpenApi } from '../interfaces/OpenApi';
import { getComment } from './getComment';
import { getOperationParameterName } from './getOperationParameterName';
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OperationParameter } from '../../../client/interfaces/OperationParameter';
import { PrimaryType } from './constants';
import { getType } from './getType';
import { getComment } from './getComment';
import { getEnum } from './getEnum';
import { getEnumType } from './getEnumType';
import { getEnumFromDescription } from './getEnumFromDescription';
import { getEnumType } from './getEnumType';
import { getModel } from './getModel';
import { getOperationParameterDefault } from './getOperationParameterDefault';
import { getOperationParameterName } from './getOperationParameterName';
import { getType } from './getType';
export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter {
const operationParameter: OperationParameter = {

View File

@ -1,9 +1,9 @@
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OpenApi } from '../interfaces/OpenApi';
import { getRef } from './getRef';
import { OperationParameters } from '../../../client/interfaces/OperationParameters';
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OperationParameter } from '../../../client/interfaces/OperationParameter';
import { OperationParameters } from '../../../client/interfaces/OperationParameters';
import { getOperationParameter } from './getOperationParameter';
import { getRef } from './getRef';
function sortByRequired(a: OperationParameter, b: OperationParameter): number {
return a.isRequired && !b.isRequired ? -1 : !a.isRequired && b.isRequired ? 1 : 0;
@ -21,9 +21,9 @@ export function getOperationParameters(openApi: OpenApi, parameters: OpenApiPara
};
// Iterate over the parameters
parameters.forEach(parameter => {
const paramRef = getRef<OpenApiParameter>(openApi, parameter);
const param = getOperationParameter(openApi, paramRef);
parameters.forEach(parameterOrReference => {
const parameter = getRef<OpenApiParameter>(openApi, parameterOrReference);
const param = getOperationParameter(openApi, parameter);
// We ignore the "api-version" param, since we do not want to add this
// as the first / default parameter for each of the service calls.

View File

@ -0,0 +1,58 @@
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { PrimaryType } from './constants';
import { getComment } from './getComment';
import { getModel } from './getModel';
import { getType } from './getType';
export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse, responseCode: number): OperationResponse {
const operationResponse: OperationResponse = {
name: '',
code: responseCode,
description: getComment(response.description)!,
export: 'generic',
type: PrimaryType.OBJECT,
base: PrimaryType.OBJECT,
template: null,
link: null,
isProperty: false,
isReadOnly: false,
isRequired: false,
isNullable: false,
imports: [],
extends: [],
enum: [],
enums: [],
properties: [],
};
// If this response has a schema, then we need to check two things:
// if this is a reference then the parameter is just the 'name' of
// this reference type. Otherwise it might be a complex schema and
// then we need to parse the schema!
if (response.schema) {
if (response.schema.$ref) {
const model = getType(response.schema.$ref);
operationResponse.export = 'reference';
operationResponse.type = model.type;
operationResponse.base = model.base;
operationResponse.template = model.template;
operationResponse.imports.push(...model.imports);
} else {
const model = getModel(openApi, response.schema);
operationResponse.export = model.export;
operationResponse.type = model.type;
operationResponse.base = model.base;
operationResponse.template = model.template;
operationResponse.link = model.link;
operationResponse.imports.push(...model.imports);
operationResponse.extends.push(...model.extends);
operationResponse.enum.push(...model.enum);
operationResponse.enums.push(...model.enums);
operationResponse.properties.push(...model.properties);
}
}
return operationResponse;
}

View File

@ -1,13 +1,10 @@
import { OpenApiResponses } from '../interfaces/OpenApiResponses';
import { getOperationResponseCode } from './getOperationResponseCode';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { getRef } from './getRef';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { OpenApiResponses } from '../interfaces/OpenApiResponses';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { getType } from './getType';
import { getModel } from './getModel';
import { getComment } from './getComment';
import { PrimaryType } from './constants';
import { getOperationResponse } from './getOperationResponse';
import { getOperationResponseCode } from './getOperationResponseCode';
import { getRef } from './getRef';
export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] {
const operationResponses: OperationResponse[] = [];
@ -20,58 +17,8 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon
const response = getRef<OpenApiResponse>(openApi, responseOrReference);
const responseCode = getOperationResponseCode(code);
// If there is a response code then we check what data we get back,
// if there is no typed data, we just return <any> so the user is still
// free to do their own casting if needed.
if (responseCode) {
const operationResponse: OperationResponse = {
name: '',
code: responseCode,
description: getComment(response.description)!,
export: 'generic',
type: PrimaryType.OBJECT,
base: PrimaryType.OBJECT,
template: null,
link: null,
isProperty: false,
isReadOnly: false,
isRequired: false,
isNullable: false,
imports: [],
extends: [],
enum: [],
enums: [],
properties: [],
};
// If this response has a schema, then we need to check two things:
// if this is a reference then the parameter is just the 'name' of
// this reference type. Otherwise it might be a complex schema and
// then we need to parse the schema!
if (response.schema) {
if (response.schema.$ref) {
const model = getType(response.schema.$ref);
operationResponse.export = 'reference';
operationResponse.type = model.type;
operationResponse.base = model.base;
operationResponse.template = model.template;
operationResponse.imports.push(...model.imports);
} else {
const model = getModel(openApi, response.schema);
operationResponse.export = model.export;
operationResponse.type = model.type;
operationResponse.base = model.base;
operationResponse.template = model.template;
operationResponse.link = model.link;
operationResponse.imports.push(...model.imports);
operationResponse.extends.push(...model.extends);
operationResponse.enum.push(...model.enum);
operationResponse.enums.push(...model.enums);
operationResponse.properties.push(...model.properties);
}
}
operationResponses.push(operationResponse);
operationResponses.push(getOperationResponse(openApi, response, responseCode));
}
}
}

View File

@ -1,6 +1,6 @@
import { PrimaryType } from './constants';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { Model } from '../../../client/interfaces/Model';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { PrimaryType } from './constants';
function areEqual(a: Model, b: Model): boolean {
const equal = a.type === b.type && a.base === b.base && a.template === b.template;

View File

@ -1,6 +1,6 @@
import { Service } from '../../../client/interfaces/Service';
import { OpenApi } from '../interfaces/OpenApi';
import { Method } from './constants';
import { OpenApi } from '../interfaces/OpenApi';
import { Service } from '../../../client/interfaces/Service';
import { getOperation } from './getOperation';
/**

View File

@ -1,7 +1,7 @@
import { stripNamespace } from './stripNamespace';
import { PrimaryType } from './constants';
import { Type } from '../../../client/interfaces/Type';
import { getMappedType, hasMappedType } from './getMappedType';
import { PrimaryType } from './constants';
import { stripNamespace } from './stripNamespace';
/**
* Parse any string value into a type object.

View File

@ -1,9 +1,9 @@
import { OpenApi } from './interfaces/OpenApi';
import { Client } from '../../client/interfaces/Client';
import { getServer } from './parser/getServer';
import { OpenApi } from './interfaces/OpenApi';
import { getModels } from './parser/getModels';
import { getServices } from './parser/getServices';
import { getServer } from './parser/getServer';
import { getServiceVersion } from './parser/getServiceVersion';
import { getServices } from './parser/getServices';
/**
* Parse the OpenAPI specification to a Client model that contains

View File

@ -1,6 +1,6 @@
import { Dictionary } from '../../../utils/types';
import { OpenApiServer } from './OpenApiServer';
import { OpenApiReference } from './OpenApiReference';
import { OpenApiServer } from './OpenApiServer';
/**
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#linkObject

View File

@ -1,13 +1,13 @@
import { Model } from '../../../client/interfaces/Model';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiSchema } from '../interfaces/OpenApiSchema';
import { getComment } from './getComment';
import { getType } from './getType';
import { Model } from '../../../client/interfaces/Model';
import { PrimaryType } from './constants';
import { getEnumType } from './getEnumType';
import { getComment } from './getComment';
import { getEnum } from './getEnum';
import { getEnumFromDescription } from './getEnumFromDescription';
import { getEnumType } from './getEnumType';
import { getModelProperties } from './getModelProperties';
import { getType } from './getType';
export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty: boolean = false, name: string = ''): Model {
const model: Model = {
@ -20,8 +20,8 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isProperty
description: getComment(definition.description),
isProperty: isProperty,
isReadOnly: definition.readOnly || false,
isNullable: definition.nullable || false,
isRequired: false,
isNullable: false,
imports: [],
extends: [],
enum: [],

View File

@ -1,9 +1,9 @@
import { Model } from '../../../client/interfaces/Model';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiSchema } from '../interfaces/OpenApiSchema';
import { getComment } from './getComment';
import { getType } from './getType';
import { Model } from '../../../client/interfaces/Model';
import { getModel } from './getModel';
import { getType } from './getType';
export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema): Model[] {
const models: Model[] = [];
@ -12,6 +12,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
const property = definition.properties[propertyName];
const propertyRequired = !!(definition.required && definition.required.includes(propertyName));
const propertyReadOnly = !!property.readOnly;
const propertyNullable = !!property.nullable;
if (property.$ref) {
const model = getType(property.$ref);
models.push({
@ -25,7 +26,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
isProperty: true,
isReadOnly: propertyReadOnly,
isRequired: propertyRequired,
isNullable: false,
isNullable: propertyNullable,
imports: model.imports,
extends: [],
enum: [],
@ -45,7 +46,7 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema):
isProperty: true,
isReadOnly: propertyReadOnly,
isRequired: propertyRequired,
isNullable: false,
isNullable: propertyNullable,
imports: model.imports,
extends: model.extends,
enum: model.enum,

View File

@ -1,7 +1,7 @@
import {Model} from '../../../client/interfaces/Model';
import {OpenApi} from '../interfaces/OpenApi';
import {getModel} from './getModel';
import {getType} from './getType';
import { Model } from '../../../client/interfaces/Model';
import { OpenApi } from '../interfaces/OpenApi';
import { getModel } from './getModel';
import { getType } from './getType';
export function getModels(openApi: OpenApi): Map<string, Model> {
const models = new Map<string, Model>();

View File

@ -1,15 +1,14 @@
import { Service } from '../../../client/interfaces/Service';
import { getServiceClassName } from './getServiceClassName';
import { OpenApiOperation } from '../interfaces/OpenApiOperation';
import { getOperationName } from './getOperationName';
import { getOperationPath } from './getOperationPath';
import { OpenApi } from '../interfaces/OpenApi';
import { getComment } from './getComment';
import { OpenApiOperation } from '../interfaces/OpenApiOperation';
import { Operation } from '../../../client/interfaces/Operation';
import { getComment } from './getComment';
import { getOperationErrors } from './getOperationErrors';
import { getOperationName } from './getOperationName';
import { getOperationParameters } from './getOperationParameters';
import { getOperationPath } from './getOperationPath';
import { getOperationResponses } from './getOperationResponses';
import { getOperationResults } from './getOperationResults';
import { getOperationErrors } from './getOperationErrors';
import { getServiceClassName } from './getServiceClassName';
export function getOperation(openApi: OpenApi, url: string, method: string, op: OpenApiOperation): Operation {
const serviceName = (op.tags && op.tags[0]) || 'Service';

View File

@ -1,5 +1,5 @@
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { OperationError } from '../../../client/interfaces/OperationError';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
export function getOperationErrors(operationResponses: OperationResponse[]): OperationError[] {
return operationResponses

View File

@ -1,11 +1,11 @@
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OpenApi } from '../interfaces/OpenApi';
import { getComment } from './getComment';
import { getOperationParameterName } from './getOperationParameterName';
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OperationParameter } from '../../../client/interfaces/OperationParameter';
import { PrimaryType } from './constants';
import { getType } from './getType';
import { getComment } from './getComment';
import { getModel } from './getModel';
import { getOperationParameterName } from './getOperationParameterName';
import { getType } from './getType';
export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter {
const operationParameter: OperationParameter = {
@ -30,6 +30,16 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame
properties: [],
};
if (parameter.$ref) {
const definitionRef = getType(parameter.$ref);
operationParameter.export = 'reference';
operationParameter.type = definitionRef.type;
operationParameter.base = definitionRef.base;
operationParameter.template = definitionRef.template;
operationParameter.imports.push(...definitionRef.imports);
return operationParameter;
}
if (parameter.schema) {
if (parameter.schema.$ref) {
const model = getType(parameter.schema.$ref);

View File

@ -1,9 +1,9 @@
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OpenApi } from '../interfaces/OpenApi';
import { getRef } from './getRef';
import { OperationParameters } from '../../../client/interfaces/OperationParameters';
import { OpenApiParameter } from '../interfaces/OpenApiParameter';
import { OperationParameter } from '../../../client/interfaces/OperationParameter';
import { OperationParameters } from '../../../client/interfaces/OperationParameters';
import { getOperationParameter } from './getOperationParameter';
import { getRef } from './getRef';
function sortByRequired(a: OperationParameter, b: OperationParameter): number {
return a.isRequired && !b.isRequired ? -1 : !a.isRequired && b.isRequired ? 1 : 0;
@ -21,9 +21,9 @@ export function getOperationParameters(openApi: OpenApi, parameters: OpenApiPara
};
// Iterate over the parameters
parameters.forEach(parameter => {
const paramRef = getRef<OpenApiParameter>(openApi, parameter);
const param = getOperationParameter(openApi, paramRef);
parameters.forEach(parameterOrReference => {
const parameter = getRef<OpenApiParameter>(openApi, parameterOrReference);
const param = getOperationParameter(openApi, parameter);
// We ignore the "api-version" param, since we do not want to add this
// as the first / default parameter for each of the service calls.

View File

@ -0,0 +1,57 @@
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { PrimaryType } from './constants';
import { getComment } from './getComment';
export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse, responseCode: number): OperationResponse {
const operationResponse: OperationResponse = {
name: '',
code: responseCode,
description: getComment(response.description)!,
export: 'generic',
type: PrimaryType.OBJECT,
base: PrimaryType.OBJECT,
template: null,
link: null,
isProperty: false,
isReadOnly: false,
isRequired: false,
isNullable: false,
imports: [],
extends: [],
enum: [],
enums: [],
properties: [],
};
// If this response has a schema, then we need to check two things:
// if this is a reference then the parameter is just the 'name' of
// this reference type. Otherwise it might be a complex schema and
// then we need to parse the schema!
// if (response.schema) {
// if (response.schema.$ref) {
// const model = getType(response.schema.$ref);
// operationResponse.export = 'reference';
// operationResponse.type = model.type;
// operationResponse.base = model.base;
// operationResponse.template = model.template;
// operationResponse.imports.push(...model.imports);
// } else {
// const model = getModel(openApi, response.schema);
// operationResponse.export = model.export;
// operationResponse.type = model.type;
// operationResponse.base = model.base;
// operationResponse.template = model.template;
// operationResponse.link = model.link;
// operationResponse.imports.push(...model.imports);
// operationResponse.extends.push(...model.extends);
// operationResponse.enum.push(...model.enum);
// operationResponse.enums.push(...model.enums);
// operationResponse.properties.push(...model.properties);
// }
// }
return operationResponse;
}

View File

@ -1,13 +1,10 @@
import { OpenApiResponses } from '../interfaces/OpenApiResponses';
import { getOperationResponseCode } from './getOperationResponseCode';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { getRef } from './getRef';
import { OpenApi } from '../interfaces/OpenApi';
import { OpenApiResponse } from '../interfaces/OpenApiResponse';
import { OpenApiResponses } from '../interfaces/OpenApiResponses';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { getType } from './getType';
import { getModel } from './getModel';
import { getComment } from './getComment';
import { PrimaryType } from './constants';
import { getOperationResponse } from './getOperationResponse';
import { getOperationResponseCode } from './getOperationResponseCode';
import { getRef } from './getRef';
export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] {
const operationResponses: OperationResponse[] = [];
@ -20,61 +17,8 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon
const response = getRef<OpenApiResponse>(openApi, responseOrReference);
const responseCode = getOperationResponseCode(code);
// If there is a response code then we check what data we get back,
// if there is no typed data, we just return <any> so the user is still
// free to do their own casting if needed.
if (responseCode) {
const operationResponse: OperationResponse = {
name: '',
code: responseCode,
description: getComment(response.description)!,
export: 'generic',
type: PrimaryType.OBJECT,
base: PrimaryType.OBJECT,
template: null,
link: null,
isProperty: false,
isReadOnly: false,
isRequired: false,
isNullable: false,
imports: [],
extends: [],
enum: [],
enums: [],
properties: [],
};
// If this response has a schema, then we need to check two things:
// if this is a reference then the parameter is just the 'name' of
// this reference type. Otherwise it might be a complex schema and
// then we need to parse the schema!
// TODO: Needs content!
// if (response.schema) {
// if (response.schema.$ref) {
// const model = getType(response.schema.$ref);
// operationResponse.export = 'reference';
// operationResponse.type = model.type;
// operationResponse.base = model.base;
// operationResponse.template = model.template;
// operationResponse.imports.push(...model.imports);
// } else {
// const model = getModel(openApi, response.schema);
// operationResponse.export = model.export;
// operationResponse.type = model.type;
// operationResponse.base = model.base;
// operationResponse.template = model.template;
// operationResponse.link = model.link;
// operationResponse.imports.push(...model.imports);
// operationResponse.extends.push(...model.extends);
// operationResponse.enum.push(...model.enum);
// operationResponse.enums.push(...model.enums);
// operationResponse.properties.push(...model.properties);
// }
// }
operationResponses.push(operationResponse);
operationResponses.push(getOperationResponse(openApi, response, responseCode));
}
}
}

View File

@ -1,6 +1,6 @@
import { PrimaryType } from './constants';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { Model } from '../../../client/interfaces/Model';
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
import { PrimaryType } from './constants';
function areEqual(a: Model, b: Model): boolean {
const equal = a.type === b.type && a.base === b.base && a.template === b.template;

View File

@ -1,6 +1,6 @@
import { Service } from '../../../client/interfaces/Service';
import { OpenApi } from '../interfaces/OpenApi';
import { Method } from './constants';
import { OpenApi } from '../interfaces/OpenApi';
import { Service } from '../../../client/interfaces/Service';
import { getOperation } from './getOperation';
/**

View File

@ -26,7 +26,7 @@ describe('getType', () => {
});
it('should convert template with primary', () => {
const type = getType('#/definitions/Link[String]');
const type = getType('#/components/schemas/Link[String]');
expect(type.type).toEqual('Link<string>');
expect(type.base).toEqual('Link');
expect(type.template).toEqual('string');
@ -34,7 +34,7 @@ describe('getType', () => {
});
it('should convert template with model', () => {
const type = getType('#/definitions/Link[Model]');
const type = getType('#/components/schemas/Link[Model]');
expect(type.type).toEqual('Link<Model>');
expect(type.base).toEqual('Link');
expect(type.template).toEqual('Model');
@ -42,7 +42,7 @@ describe('getType', () => {
});
it('should have double imports', () => {
const type = getType('#/definitions/Link[Link]');
const type = getType('#/components/schemas/Link[Link]');
expect(type.type).toEqual('Link<Link>');
expect(type.base).toEqual('Link');
expect(type.template).toEqual('Link');
@ -50,7 +50,7 @@ describe('getType', () => {
});
it('should convert generic', () => {
const type = getType('#/definitions/Link', 'Link');
const type = getType('#/components/schemas/Link', 'Link');
expect(type.type).toEqual('T');
expect(type.base).toEqual('T');
expect(type.template).toEqual(null);

View File

@ -1,7 +1,7 @@
import { stripNamespace } from './stripNamespace';
import { Type } from '../../../client/interfaces/Type';
import { getMappedType, hasMappedType } from './getMappedType';
import { PrimaryType } from './constants';
import {PrimaryType} from './constants';
import {Type} from '../../../client/interfaces/Type';
import {getMappedType, hasMappedType} from './getMappedType';
import {stripNamespace} from './stripNamespace';
/**
* Parse any string value into a type object.

View File

@ -1,5 +1,5 @@
import { getFileName } from './getFileName';
import { Language } from '../index';
import { getFileName } from './getFileName';
describe('getFileName', () => {
it('should convert to correct file name', () => {

View File

@ -1,5 +1,5 @@
import { getModelNames } from './getModelNames';
import { Model } from '../client/interfaces/Model';
import { getModelNames } from './getModelNames';
describe('getModelNames', () => {
it('should return sorted list', () => {

View File

@ -1,5 +1,5 @@
import { getOpenApiSpec } from './getOpenApiSpec';
import * as fs from 'fs';
import { getOpenApiSpec } from './getOpenApiSpec';
jest.mock('fs');

View File

@ -1,5 +1,5 @@
import { getServiceNames } from './getServiceNames';
import { Service } from '../client/interfaces/Service';
import { getServiceNames } from './getServiceNames';
describe('getServiceNames', () => {
it('should return sorted list', () => {

View File

@ -1,5 +1,5 @@
import { readHandlebarsTemplate } from './readHandlebarsTemplate';
import * as fs from 'fs';
import { readHandlebarsTemplate } from './readHandlebarsTemplate';
jest.mock('fs');

View File

@ -1,5 +1,5 @@
import * as fs from 'fs';
import * as Handlebars from 'handlebars';
import * as fs from 'fs';
/**
* Read and compile the Handlebars template.

View File

@ -1,7 +1,7 @@
import { readHandlebarsTemplates } from './readHandlebarsTemplates';
import * as fs from 'fs';
import { Language } from '../index';
import * as glob from 'glob';
import { Language } from '../index';
import { readHandlebarsTemplates } from './readHandlebarsTemplates';
jest.mock('fs');
jest.mock('glob');

View File

@ -1,9 +1,9 @@
import * as Handlebars from 'handlebars';
import { readHandlebarsTemplate } from './readHandlebarsTemplate';
import { Language } from '../index';
import * as path from 'path';
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
import * as glob from 'glob';
import * as path from 'path';
import { Language } from '../index';
import { readHandlebarsTemplate } from './readHandlebarsTemplate';
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
export interface Templates {
index: Handlebars.TemplateDelegate;

View File

@ -1,13 +1,13 @@
import { writeClient } from './writeClient';
import * as fs from 'fs';
import * as glob from 'glob';
import * as mkdirp from 'mkdirp';
import * as rimraf from 'rimraf';
import * as fs from 'fs';
import { Client } from '../client/interfaces/Client';
import { Templates } from './readHandlebarsTemplates';
import { HttpClient, Language } from '../index';
import * as glob from 'glob';
import { Model } from '../client/interfaces/Model';
import { Service } from '../client/interfaces/Service';
import { Templates } from './readHandlebarsTemplates';
import { writeClient } from './writeClient';
jest.mock('rimraf');
jest.mock('mkdirp');

View File

@ -1,14 +1,14 @@
import { writeClientModels } from './writeClientModels';
import { writeClientServices } from './writeClientServices';
import { Client } from '../client/interfaces/Client';
import * as path from 'path';
import * as mkdirp from 'mkdirp';
import * as rimraf from 'rimraf';
import { Templates } from './readHandlebarsTemplates';
import { writeClientIndex } from './writeClientIndex';
import { HttpClient, Language } from '../index';
import * as fs from 'fs';
import * as glob from 'glob';
import * as mkdirp from 'mkdirp';
import * as path from 'path';
import * as rimraf from 'rimraf';
import { Client } from '../client/interfaces/Client';
import { HttpClient, Language } from '../index';
import { Templates } from './readHandlebarsTemplates';
import { writeClientIndex } from './writeClientIndex';
import { writeClientModels } from './writeClientModels';
import { writeClientServices } from './writeClientServices';
import { writeClientSettings } from './writeClientSettings';
/**

View File

@ -1,10 +1,10 @@
import { writeClientIndex } from './writeClientIndex';
import * as fs from 'fs';
import { Client } from '../client/interfaces/Client';
import { Language } from '../index';
import { Model } from '../client/interfaces/Model';
import { Service } from '../client/interfaces/Service';
import { Templates } from './readHandlebarsTemplates';
import { writeClientIndex } from './writeClientIndex';
jest.mock('fs');

View File

@ -1,11 +1,11 @@
import { Client } from '../client/interfaces/Client';
import * as fs from 'fs';
import * as path from 'path';
import { Client } from '../client/interfaces/Client';
import { Language } from '../index';
import { Templates } from './readHandlebarsTemplates';
import { getFileName } from './getFileName';
import { getModelNames } from './getModelNames';
import { getServiceNames } from './getServiceNames';
import { Language } from '../index';
import { getFileName } from './getFileName';
import { Templates } from './readHandlebarsTemplates';
/**
* Generate the OpenAPI client index file using the Handlebar template and write it to disk.

View File

@ -1,8 +1,8 @@
import { writeClientModels } from './writeClientModels';
import * as fs from 'fs';
import { Model } from '../client/interfaces/Model';
import { Language } from '../index';
import { Model } from '../client/interfaces/Model';
import { Templates } from './readHandlebarsTemplates';
import { writeClientModels } from './writeClientModels';
jest.mock('fs');

View File

@ -1,11 +1,11 @@
import * as fs from 'fs';
import { Model } from '../client/interfaces/Model';
import * as path from 'path';
import { Language } from '../index';
import { getFileName } from './getFileName';
import { exportModel } from './exportModel';
import { Model } from '../client/interfaces/Model';
import { Templates } from './readHandlebarsTemplates';
import { exportModel } from './exportModel';
import { format } from './format';
import { getFileName } from './getFileName';
/**
* Generate Models using the Handlebar template and write to disk.

View File

@ -1,8 +1,8 @@
import { writeClientServices } from './writeClientServices';
import * as fs from 'fs';
import { Service } from '../client/interfaces/Service';
import { Language } from '../index';
import { Service } from '../client/interfaces/Service';
import { Templates } from './readHandlebarsTemplates';
import { writeClientServices } from './writeClientServices';
jest.mock('fs');

View File

@ -1,11 +1,11 @@
import * as fs from 'fs';
import * as path from 'path';
import { Service } from '../client/interfaces/Service';
import { Language } from '../index';
import { getFileName } from './getFileName';
import { exportService } from './exportService';
import { Service } from '../client/interfaces/Service';
import { Templates } from './readHandlebarsTemplates';
import { exportService } from './exportService';
import { format } from './format';
import { getFileName } from './getFileName';
/**
* Generate Services using the Handlebar template and write to disk.

View File

@ -1,9 +1,9 @@
import { Client } from '../client/interfaces/Client';
import * as fs from 'fs';
import * as path from 'path';
import { Client } from '../client/interfaces/Client';
import { HttpClient, Language } from '../index';
import { getFileName } from './getFileName';
import { Templates } from './readHandlebarsTemplates';
import { getFileName } from './getFileName';
export function writeClientSettings(client: Client, language: Language, httpClient: HttpClient, templates: Templates, outputPath: string): void {
const fileName = getFileName('OpenAPI', language);

File diff suppressed because it is too large Load Diff

View File

@ -4,42 +4,83 @@ const fs = require('fs');
describe('generation', () => {
describe('typescript', () => {
describe('v2', () => {
OpenAPI.generate(
'./test/mock/spec-v2.json',
'./test/result/v2/typescript/',
OpenAPI.Language.TYPESCRIPT,
OpenAPI.HttpClient.FETCH,
);
describe('typescript', () => {
test.each(glob
.sync('./test/result/v2/typescript/**/*.ts')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
OpenAPI.generate(
'./test/mock/spec-v2.json',
'./test/result/v2/typescript/',
OpenAPI.Language.TYPESCRIPT,
OpenAPI.HttpClient.FETCH,
);
test.each(glob
.sync('./test/result/v2/typescript/**/*.ts')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
});
});
describe('javascript', () => {
OpenAPI.generate(
'./test/mock/spec-v2.json',
'./test/result/v2/javascript/',
OpenAPI.Language.JAVASCRIPT,
OpenAPI.HttpClient.XHR,
);
test.each(glob
.sync('./test/result/v2/javascript/**/*.js')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
});
});
});
describe('javascript', () => {
describe('v3', () => {
OpenAPI.generate(
'./test/mock/spec-v2.json',
'./test/result/v2/javascript/',
OpenAPI.Language.JAVASCRIPT,
OpenAPI.HttpClient.XHR,
);
describe('typescript', () => {
test.each(glob
.sync('./test/result/v2/javascript/**/*.js')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
OpenAPI.generate(
'./test/mock/spec-v3.json',
'./test/result/v3/typescript/',
OpenAPI.Language.TYPESCRIPT,
OpenAPI.HttpClient.FETCH,
);
test.each(glob
.sync('./test/result/v3/typescript/**/*.ts')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
});
});
describe('javascript', () => {
OpenAPI.generate(
'./test/mock/spec-v3.json',
'./test/result/v3/javascript/',
OpenAPI.Language.JAVASCRIPT,
OpenAPI.HttpClient.XHR,
);
test.each(glob
.sync('./test/result/v3/javascript/**/*.js')
.map(file => [file])
)('file(%s)', file => {
const content = fs.readFileSync(file, 'utf8').toString();
expect(content).toMatchSnapshot(file);
});
});
});
});

View File

@ -1800,6 +1800,13 @@ eslint-plugin-prettier@3.1.1:
dependencies:
prettier-linter-helpers "^1.0.0"
eslint-plugin-sort-imports-es6-autofix@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-sort-imports-es6-autofix/-/eslint-plugin-sort-imports-es6-autofix-0.5.0.tgz#dabae09a457eac6e95c52d8edd7855f576d014b6"
integrity sha512-KEX2Uz6bAs67jDYiH/OT1xz1E7AzIJJOIRg1F7OnFAfUVlpws3ldSZj5oZySRHfoVkWqDX9GGExYxckdLrWhwg==
dependencies:
eslint "^6.2.2"
eslint-scope@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9"
@ -1863,6 +1870,49 @@ eslint@6.6.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
eslint@^6.2.2:
version "6.7.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.0.tgz#766162e383b236e61d873697f82c3a3e41392020"
integrity sha512-dQpj+PaHKHfXHQ2Imcw5d853PTvkUGbHk/MR68KQUl98EgKDCdh4vLRH1ZxhqeQjQFJeg8fgN0UwmNhN3l8dDQ==
dependencies:
"@babel/code-frame" "^7.0.0"
ajv "^6.10.0"
chalk "^2.1.0"
cross-spawn "^6.0.5"
debug "^4.0.1"
doctrine "^3.0.0"
eslint-scope "^5.0.0"
eslint-utils "^1.4.3"
eslint-visitor-keys "^1.1.0"
espree "^6.1.2"
esquery "^1.0.1"
esutils "^2.0.2"
file-entry-cache "^5.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.3.0"
lodash "^4.17.14"
minimatch "^3.0.4"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
optionator "^0.8.3"
progress "^2.0.0"
regexpp "^2.0.1"
semver "^6.1.2"
strip-ansi "^5.2.0"
strip-json-comments "^3.0.1"
table "^5.2.3"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
espree@^6.1.2:
version "6.1.2"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d"
@ -2022,7 +2072,7 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
fast-levenshtein@~2.0.4:
fast-levenshtein@~2.0.4, fast-levenshtein@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@ -2219,6 +2269,13 @@ globals@^11.1.0, globals@^11.7.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globals@^12.1.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13"
integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==
dependencies:
type-fest "^0.8.1"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
@ -3598,6 +3655,18 @@ optionator@^0.8.1, optionator@^0.8.2:
type-check "~0.3.2"
wordwrap "~1.0.0"
optionator@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
dependencies:
deep-is "~0.1.3"
fast-levenshtein "~2.0.6"
levn "~0.3.0"
prelude-ls "~1.1.2"
type-check "~0.3.2"
word-wrap "~1.2.3"
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
@ -4646,6 +4715,11 @@ type-fest@^0.5.2:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2"
integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==
type-fest@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
typescript@3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
@ -4832,6 +4906,11 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2"
word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"